"Swift"编程语言

来自英文文档、百度翻译以及自己没过4级的渣渣英语功底,为了自己以后看起来方便


About Swift

关于"海燕"


IMPORTANT

重要


This is a preliminary document for an API or technology in development. Apple is supplying this information to help you plan for the adoption of the technologies and programming interfaces described herein for use on Apple-branded products. This information is subject to change, and software implemented according to this document should be tested with final operating system software and final documentation. Newer versions of this document may be provided with future seeds of the API or technology.

这是一个用于开发的API和技术的初期文档。

苹果公司正在提供这些信息来帮助你把这项技术和编程接口应用到你的苹果品牌产品中。

这些信息是随时变化的,根据这个文档实现的软件须要在终于的操作系统软件和终于文档上測试。新版本号的文档将会提供API和这项技术的未来种子(= =没翻译明确)。


Swift is a new programming language for iOS and OS X apps that builds on the best of C and Objective-C, without the constraints of C compatibility. Swift adopts safe programming patterns and adds modern features to make programming easier, more flexible, and more fun. Swift’s clean slate, backed by the mature and much-loved Cocoa and Cocoa Touch frameworks, is an opportunity to reimagine how software development works.

"海燕"是一个建立在C和Objective-C基础上。没有C语言兼容性约束的用于开发IOS和OS X操作系统应用的新语言。

"海燕"採用安全编程方式,加入了现代特征来使编程变得更简单,更灵活,更有趣。

"海燕"清白的历史,在成熟的受欢迎的Cocoa和Cocoa Touch框架的支持下,这在软件开发工作中是一个多么充满机遇的构想。


Swift has been years in the making. Apple laid the foundation for Swift by advancing our existing compiler, debugger, and framework infrastructure. We simplified memory management with Automatic Reference Counting (ARC). Our framework stack, built on the solid base of Foundation and Cocoa, has been modernized and standardized throughout. Objective-C itself has evolved to support blocks, collection literals, and modules, enabling framework adoption of modern language technologies without disruption. Thanks to this groundwork, we can now introduce a new language for the future of Apple software development.

"海燕"已经酝酿多年。

苹果公司提出这个"海燕"语言基础来推进已经存在的编译器。调试器和基础架构。我们使用ARC来使内存管理变得简单。

我们建立在Foundation和Cocoa基础上的框架层,已经现代化和规范化。Objective-C本身已经发展到支持代码块,容器,单元模块,这使不间断的採用现代语言成为可能。(是这个意思吧?= =)多亏于这个基础。我们如今能够为苹果软件开发的将来引入这样一个新语言。


Swift feels familiar to Objective-C developers. It adopts the readability of Objective-C’s named parameters and the power of Objective-C’s dynamic object model. It provides seamless access to existing Cocoa frameworks and mix-and-match interoperability with Objective-C code. Building from this common ground, Swift introduces many new features and unifies the procedural and object-oriented portions of the language.

Objective-C的开发人员会对于"雨燕"感到熟悉。"雨燕"基于易读的Objective-C的命名參数和Objective-C动态对象模式的动力。

它能够无缝的连接到已经存在的Cocoa框架并支持和Objective-C的混编。基于这些共同点。"雨燕"引入了很多特性、结合程序和语言的面向对象部分。(这里断句断不明确了= =)


Swift is friendly to new programmers. It is the first industrial-quality systems programming language that is as expressive and enjoyable as a scripting language. It supports playgrounds, an innovative feature that allows programmers to experiment with Swift code and see the results immediately, without the overhead of building and running an app.

"雨燕"(下面直接称为"swift")对新的编程人员是友善的。

这是第一个工业质量(不懂= =)级别的系统编程语言。它像一个脚本语言一样富有表现力和有趣味。它支持的playgrounds,是一个革新性的特性,它同意程序猿在编写swift代码的同一时候立马看到那些结果,没有建立和执行一个应用程序的开销。


Swift combines the best in modern language thinking with wisdom from the wider Apple engineering culture. The compiler is optimized for performance, and the language is optimized for development, without compromising on either. It’s designed to scale from “hello, world” to an entire operating system. All this makes Swift a sound future investment for developers and for Apple.

swift运用最好的现代语言思想来思考苹果编程文化中的智慧。编译器的性能更优,语言的开发更优。这两者的提升不放弃当中一项。它的设计从"hello,world"一直衡量到整个操作系统。全部这些使得swift成为一个对于开发人员和对于苹果来说都是一个健康的未来。(应该就是你选择它不会错的意思= =)


Swift is a fantastic way to write iOS and OS X apps, and will continue to evolve with new features and capabilities. Our goals for Swift are ambitious. We can’t wait to see what you create with it.

swift是一个作为开发IOS和 OS X应用程序非常好的方式。而且它会继续开发新的特性和能力。我们的目标是雄心壮志的swift,我们迫不及待的想看到你创建出一个什么样的它。


A Swift Tour

一次雨燕之旅


Tradition suggests that the first program in a new language should print the words “Hello, world” on the screen. In Swift, this can be done in a single line:
传统惯例,一个新语言的第一个程序应该在屏幕上打印"Hello, wordld"。在swift中,这个工作能够用一行来完毕:
println(Hello, world)

If you have written code in C or Objective-C, this syntax looks familiar to you—in Swift, this line of code is a complete program. You don’t need to import a separate library for functionality like input/output or string handling. Code written at global scope is used as the entry point for the program, so you don’t need a mainfunction. You also don’t need to write semicolons at the end of every statement.
假设你以前是写C或者Objective-C代码的,这语法你看起来一定会很熟悉。在swift中。这一行代码就是一个完整的程序。你不须要导入单独功能(像IO或者字符串处理)的库。写在全局范围内的代码即是程序的入口,所以你并不须要main函数。

你相同不须要在每一个语句后面写分号。


This tour gives you enough information to start writing code in Swift by showing you how to accomplish a variety of programming tasks. Don’t worry if you don’t understand something—everything introduced in this tour is explained in detail in the rest of this book.
本节会给你足够的信息来让你開始编写swifit代码。并教你怎样完毕各种编程任务。

假设你看不懂当中的一些,(没关系,)在本节中引出的全部东西。都会在这本书的其余部分详解。


NOTE
提示

For the best experience, open this chapter as a playground in Xcode. Playgrounds allow you to edit the code listings and see the result immediately.
为了获得更好的一眼,在Xcode中打开本章提到的playground。它将同意你编辑代码列表并马上看到结果。

Simple Values

简单的值

Use let to make a constant and var to make a variable. The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once. This means you can use constants to name a value that you determine once but use in many places.
使用let来声明一个常量。使用var来声明一个变量。

一个常量的值不须要在编译的时候被知道,但它必须被赋值过一次。这意味着你能够仅仅将常量赋值一次但能够在多处使用。


var myVariable = 42
myVariable = 50
let myConstant = 42

A constant or variable must have the same type as the value you want to assign to it. However, you don’t always have to write the type explicitly. Providing a value when you create a constant or variable lets the compiler infer its type. In the example above, the compiler infers that myVariable is an integer because its initial value is a integer.
一个常量或变量的的类型必须与你想给予它的值的类型一致。

然后,你不用一定要明白的写出类型。当你建立一个常量或变量时。你提供一个值来让编译器判断它的类型。在上面的样例中,编译器会判断出myVariable是一个整形。由于它被赋值了一个整形。


If the initial value doesn’t provide enough information (or if there is no initial value), specify the type by writing it after the variable, separated by a colon.
假设一个初始化的值并不能提供足够的信息(或者他根本就没有初始值),将类型写在这个变量的后面。并用冒号隔
开。
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70

EXPERIMENT
实验

Create a constant with an explicit type of Float and a value of 4.
创建一个值为4的显式浮点类型的常量。


Values are never implicitly converted to another type. If you need to convert a value to a different type, explicitly make an instance of the desired type.
值从来不会隐式的转化为还有一种类型。假设你须要把一个值转换成另外的类型,明白的创造一个所需类型的实例。
let label = "The width is "
let width = 94
let widthLabel = label + String(width)

EXPERIMENT
实验

Try removing the conversion to String from the last line. What error do you get?

在上一行中,尝试移除到String的转换。你会得到什么错误?

There’s an even simpler way to include values in strings: Write the value in parentheses, and write a backslash () before the parentheses. For example:
有一个更简单的办法去在字符串中包括一个值,就是将值写在括号里,并在括号的前面加\,比如:
let apples = 3
let oranges = 5
let appleSummary = "I have (apples) apples."
let fruitSummary = "I have (apples + oranges) pieces of fruit."

EXPERIMENT
实验


Use () to include a floating-point calculation in a string and to include someone’s name in a greeting.
使用()来在字符串中包括一个浮点运算。再包括一个问候某人的名字。

Create arrays and dictionaries using brackets ([]), and access their elements by writing the index or key in brackets.
使用放括号[]来创建数组和字典,并通过写在放括号里的索引或键訪问它们的元素。
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
 
var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

To create an empty array or dictionary, use the initializer syntax.
使用初始化语法来构建一个空的数组或字典。


let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()

 type information can be inferred, you can write an empty array as [] and an empty dictionary as [:]—for example, when you set a new value for a variable or pass an argument to a function.
类型信息能够被判断出来,你能够写一个空的数组像[]和一个空的字典像[:]--比如。当你给变量设置一个新值或传递參数时。
shoppingList = []   // Went shopping and bought everything.

Control Flow

控制流

Use if and switch to make conditionals, and use for-inforwhile, and do-while to make loops. Parentheses around the condition or loop variable are optional. Braces around the body are required.
使用if和switch生成条件句,使用for-in,for,while和do-while生成循环语句。

包围条件或者循环变量的圆括号是可选的。身体周围的大括号是必须的。

let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
teamScore

In an if statement, the conditional must be a Boolean expression—this means that code such as if score { ... } is an error, not an implicit comparison to zero.
在if语句中,条件必须是一个boolean表达式,这意味着这种代码if score{...}是一个错误,没有隐含的对零的比較。(就是说"非零是真"在swift中不存在)

You can use if and let together to work with values that might be missing. These values are represented as optionals. An optional value either contains a value or contains nil to indicate that the value is missing. Write a question mark (?

) after the type of a value to mark the value as optional.

你能够同一时候使用if和let与那些可能会丢失的值连在一起。(是这么翻译吧?个人理解就是初始化的值)这些值表现为可变。一个可变值可能包括一个值或一个nil来代表该值丢失。

在值的类型后面写一个问号标记(?)该值的类型可选。

var optionalString: String? = "Hello"
optionalString == nil
 
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, (name)"
}

EXPERIMENT
实验


Change optionalName to nil. What greeting do you get? Add an else clause that sets a different greeting if optionalName is nil.
改变optionalName的值为nil。greeting会变成什么?假设optionalName为空,加入一个else分句来设置不同的greeting。


If the optional value is nil, the conditional is false and the code in braces is skipped. Otherwise, the optional value is unwrapped and assigned to the constant after let, which makes the unwrapped value available inside the block of code.
假设一个可变值为nil。条件是false,则大括号里的代码被跳过。

否则,let后面的指定的可变值被赋值为这个常量,这使得被指定的值可用并进入大括号里的代码。


Switches support any kind of data and a wide variety of comparison operations—they aren’t limited to integers and tests for equality.
switch语句支持随意类型的数据和各种各样的比較操作。它们不限于整数和不过为了測试相等。
let vegetable = "red pepper"
switch vegetable {
case "celery":
    let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
    let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
    let vegetableComment = "Is it a spicy (x)?"
default:
    let vegetableComment = "Everything tastes good in soup."
}

EXPERIMENT
实验


Try removing the default case. What error do you get?


试着移除default分句,看看会报什么错?

After executing the code inside the switch case that matched, the program exits from the switch statement. Execution doesn’t continue to the next case, so there is no need to explicitly break out of the switch at the end of each case’s code.
在运行了switch case匹配成功的分支代码后。程序从switch声明中退出。

运行的状态不会继续到下一个分支。所以不须要在每个case代码的后面确切的标注退出switch。


You use for-in to iterate over items in a dictionary by providing a pair of names to use for each key-value pair.
通过提供一个键值对的名字使用for-in叠代字典中的每个元素。
let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}
largest

EXPERIMENT
实验


Add another variable to keep track of which kind of number was the largest, as well as what that largest number was.
加入其它变量使这与那种数最大无关,也就是数最大是什么。(这句全然没翻译明确)

Use while to repeat a block of code until a condition changes. The condition of a loop can be at the end instead, ensuring that the loop is run at least once.
使用while来反复一段代码知道条件改变。这个循环的条件能够在结尾处替换。来确保这个循环至少运行一次。
var n = 2
while n < 100 {
    n = n * 2
}
n
 
var m = 2
do {
    m = m * 2
} while m < 100
m

You can keep an index in a loop—either by using .. to make a range of indexes or by writing an explicit initialization, condition, and increment. These two loops do the same thing:
你能够保持一个索引在循环中。或者使用..来确立一个索引的范围或者使用明白的初始值,条件和增量。以下的两个循环做了相同的事情:
var firstForLoop = 0
for i in 0..3 {
    firstForLoop += i
}
firstForLoop
 
var secondForLoop = 0
for var i = 0; i < 3; ++i {
    secondForLoop += 1
}
secondForLoop
Use .. to make a range that omits its upper value, and use ... to make a range that includes both values.
使用..来确定一个不包括最大值的范围,使用...确定一个包括全部值的范围。

Functions and Closures

函数和闭包(Closures怎么翻译?)

Use func to declare a function. Call a function by following its name with a list of arguments in parentheses. Use -> to separate the parameter names and types from the function’s return type.
使用func来描写叙述一个函数。通过跟在名字后面括号里的一个參数列表调用函数。使用->来切割參数名称和函数返回值类型。
func greet(name: String, day: String) -> String {
    return "Hello (name), today is (day)."
}
greet("Bob", "Tuesday")

EXPERIMENT
实验

Remove the day parameter. Add a parameter to include today’s lunch special in the greeting.
移除day參数。加入一个參数来包括今天午餐特别的问候。


Use a tuple to return multiple values from a function.
使用数组从一个函数中返回多值。

func getGasPrices() -> (Double, Double, Double) {
    return (3.59, 3.69, 3.79)
}
getGasPrices()

Functions can also take a variable number of arguments, collecting them into an array.
函数相同能够接受数目可变的參数,把它们收集到一个数组中。


func sumOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
sumOf()
sumOf(42, 597, 12)

EXPERIMENT
实验

Write a function that calculates the average of its arguments.
写一个函数,要求计算传入參数的平均值。

Functions can be nested. Nested functions have access to variables that were declared in the outer function. You can use nested functions to organize the code in a function that is long or complex.
函数能够嵌套。嵌套函数能够訪问在外部函数声明的变量。

在函数过长或者非常复杂的时候,你能够使用嵌套函数来组织代码。


func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}
returnFifteen()

Functions are a first-class type. This means that a function can return another function as its value.
函数是一个first-class类型。这意味着一个函数能够返回还有一个函数作为它的值。
func makeIncrementer() -> (Int -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)

A function can take another function as one of its arguments.
一个函数能够把还有一个函数作为它当中一个參数。

func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)

Functions are actually a special case of closures. You can write a closure without a name by surrounding code with braces ({}). Use in to separate the arguments and return type from the body.
函数实际上是一个特殊情况下的闭包

你能够写一个被大括号{}包裹着的没有名字的匿名方法。在函数体中使用in来分隔參数和返回值。


numbers.map({
    (number: Int) -> Int in
    let result = 3 * number
    return result
    })

EXPERIMENT
实验

Rewrite the closure to return zero for all odd numbers.
重写这个匿名方法来返回全部的奇数。


You have several options for writing closures more concisely. When a closure’s type is already known, such as the callback for a delegate, you can omit the type of its parameters, its return type, or both. Single statement closures implicitly return the value of their only statement.
你有几个选项来使你的书写那些闭包更简单介绍。

当一个闭包的类型已知时,就像一个代理的回调。你能够省略它们的參数类型,它们的返回值,或者都省略。一个简单的闭包声明只隐式的返回它们声明的返回值。

numbers.map({ number in 3 * number })

You can refer to parameters by number instead of by name—this approach is especially useful in very short closures. A closure passed as the last argument to a function can appear immediately after the parentheses.
你能够參考參数的数量而不是名字。在一个间断的闭包中这是很实用的的方法。一个匿名函数把最后一个參数传递给一个函数,能够立马出如今圆括号后面。(有点懵。。

。)

sort([1, 5, 3, 12, 2]) { $0 > $1 }

Objects and Classes

对象和类

Use class followed by the class’s name to create a class. A property declaration in a class is written the same way as a constant or variable declaration, except that it is in the context of a class. Likewise, method and function declarations are written the same way.
使用class在类名前面来建立一个类。

类中的属性的声明方式和一个变量或常量的声明一样。除非它在类的上下文中。相同的,方法和函数的声明也都相同。

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with (numberOfSides) sides."
    }
}

EXPERIMENT
实验

Add a constant property with let, and add another method that takes an argument.
使用let加入一个常量属性,再加入一个接收一个參数的方法。

Create an instance of a class by putting parentheses after the class name. Use dot syntax to access the properties and methods of the instance.
通过在类名后面加上圆括号来创建一个类的实例。使用点语法来訪问该实例的属性和方法。

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

This version of the Shape class is missing something important: an initializer to set up the class when an instance is created. Use init to create one.
这个版本号的Shape类缺失了一些重要的东西:当实例被创建时候的初始化该类。使用init来创建一个。

class NamedShape {
    var numberOfSides: Int = 0
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func simpleDescription() -> String {
        return "A shape with (numberOfSides) sides."
    }
}

Notice how self is used to distinguish the name property from the name argument to the initializer. The arguments to the initializer are passed like a function call when you create an instance of the class. Every property needs a value assigned—either in its declaration (as with numberOfSides) or in the initializer (as with name).
注意,使用self怎样来区分属性名字和初始化函数中的參数名字。

当你创建一个类的实例时。这些參数对于构造器像一个函数一样被调用。每个属性须要被数值。在它被声明的时候(像numberOfSides)或该类初始化的时候(像name)。


Use deinit to create a deinitializer if you need to perform some cleanup before the object is deallocated.
假设你须要在对象被销毁前做一些清楚工作。使用deinit来创建一个释放器。

Subclasses include their superclass name after their class name, separated by a colon. There is no requirement for classes to subclass any standard root class, so you can include or omit a superclass as needed.
子类包括他们父类的名在在他们的名字后面。用一个冒号分开。

不要求子类必须继承一个标准的根类。所以你能够按需包括一个父类或省略它。


Methods on a subclass that override the superclass’s implementation are marked with override—overriding a method by accident, without override, is detected by the compiler as an error. The compiler also detects methods with override that don’t actually override any method in the superclass.
当子类的方法覆盖父类的实现时,使用override。假设没有override,编译器会检測报错。编译器也会检測override没有覆盖到不论什么一个父类的方法。

class Square: NamedShape {
    var sideLength: Double
    
    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }
    
    func area() ->  Double {
        return sideLength * sideLength
    }
    
    override func simpleDescription() -> String {
        return "A square with sides of length (sideLength)."
    }
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()

Make another subclass of NamedShape called Circle that takes a radius and a name as arguments to its initializer. Implement an area and a describe method on the Circle class.
创建还有一个名字叫Circle子类,继承于NamedSpace,使用半径和名称作为它的初始化參数。在Circle类里实现一个area和describe方法。


In addition to simple properties that are stored, properties can have a getter and a setter.
除了简单的属性被加载外,属性能够有一个getting和一个setting。
class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0
    
    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }
    
    var perimeter: Double {
    get {
        return 3.0 * sideLength
    }
    set {
        sideLength = newValue / 3.0
    }
    }
    
    override func simpleDescription() -> String {
        return "An equilateral triagle with sides of length (sideLength)."
    }
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength

In the setter for perimeter, the new value has the implicit name newValue. You can provide an explicit name in parentheses after set.
在perimeter的setter中,这个新的值有一个隐式的名字newValue。你能够在set后面的括号里提供一个确切的名字。


Notice that the initializer for the EquilateralTriangle class has three different steps:

  1. Setting the value of properties that the subclass declares.

  2. Calling the superclass’s initializer.

  3. Changing the value of properties defined by the superclass. Any additional setup work that uses methods, getters, or setters can also be done at this point.

注意,EquilateralTriangle在初始化的时候有三个不同的步骤:
1.设置子类声明的属性的值。
2.调用父类的构造方法。

3.改变父类定义的属性的值。不论什么格外的设置工作,getters或者setters都会在这一步完毕。

If you don’t need to compute the property but still need to provide code that is run before and after setting a new value, use willSet and didSet. For example, the class below ensures that the side length of its triangle is always the same as the side length of its square.
假设你不须要计算性能但仍需提供执行之前和之后设置新值的代码,使用willset和didset。以下的类保证这个三角形的编程一直和正方形的边长相等。



class TriangleAndSquare {
    var triangle: EquilateralTriangle {
    willSet {
        square.sideLength = newValue.sideLength
    }
    }
    var square: Square {
    willSet {
        triangle.sideLength = newValue.sideLength
    }
    }
    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EquilateralTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength

Methods on classes have one important difference from functions. Parameter names in functions are used only within the function, but parameters names in methods are also used when you call the method (except for the first parameter). By default, a method has the same name for its parameters when you call it and within the method itself. You can specify a second name, which is used inside the method.

类中的方法相对于函数有一个非常大的差别。函数的參数名仅仅能在函数内部使用,可是方法的參数名能够在你调用方法是使用(除了第一个參数)。默认情况下。当你在函数内部调用自身方法具有相同名字的參数时,你能够在方法内部指定第二个名字。

class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes times: Int) {
        count += amount * times
    }
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)

When working with optional values, you can write ? before operations like methods, properties, and subscripting. If the value before the ?

 is nil, everything after the ? is ignored and the value of the whole expression is nil. Otherwise, the optional value is unwrapped, and everything after the ?

 acts on the unwrapped value. In both cases, the value of the whole expression is an optional value.

当操作可变值的时候,你能够在方法,属性和下标的操作前加上?。假设在?前面的值是空,则?之后的一切东西会被忽略,整个表达式为空。否则。假设这个可变值已经被赋值,则在?之后的全部操作都将被运行。

不管如何。这个表达式的值都是一个可变值。


let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

Enumerations and Structures

枚举和结构

Use enum to create an enumeration. Like classes and all other named types, enumerations can have methods associated with them.
使用enum来创建一个枚举类型。就像类和全部其它命名类型一样,枚举类型也有方法和他们联系起来。
enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    func simpleDescription() -> String {
        switch self {
        case .Ace:
            return "ace"
        case .Jack:
            return "jack"
        case .Queen:
            return "queen"
        case .King:
            return "king"
        default:
            return String(self.toRaw())
        }
    }
}
let ace = Rank.Ace
let aceRawValue = ace.toRaw()

EXPERIMENT
实验

Write a function that compares two Rank values by comparing their raw values.
写一个函数通过比較两个Rank的初始值来比較他们。

In the example above, the raw value type of the enumeration is Int, so you only have to specify the first raw value. The rest of the raw values are assigned in order. You can also use strings or floating-point numbers as the raw type of an enumeration.
在上一个样例中,枚举类型的初始值类型是Int。那么你仅仅需指定第一个初始值。其余的初始值会依次分配。你也能够使用字符串或者浮点数作为枚举的原始类型。

Use the toRaw and fromRaw functions to convert between the raw value and the enumeration value.
使用toRaw和fromRaw函数在初始值和枚举值之间转换。

if let convertedRank = Rank.fromRaw(3) {
    let threeDescription = convertedRank.simpleDescription()
}

The member values of an enumeration are actual values, not just another way of writing their raw values. In fact, in cases where there isn’t a meaningful raw value, you don’t have to provide one.
枚举成员的值是实际值。不不过他们原始值的还有一种表达方式。

其实,没有一个有意义的原始值,你不须要提供一个。

enum Suit {
    case Spades, Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
        case .Spades:
            return "spades"
        case .Hearts:
            return "hearts"
        case .Diamonds:
            return "diamonds"
        case .Clubs:
            return "clubs"
        }
    }
}
let hearts = Suit.Hearts
let heartsDescription = hearts.simpleDescription()

EXPERIMENT
实验


Add a color method to Suit that returns “black” for spades and clubs, and returns “red” for hearts and diamonds.
给Suit加入一个color方法。假设是spadesclubs返回black。假设是hearts和diamonds返回red。


Notice the two ways that the Hearts member of the enumeration is referred to above: When assigning a value to the hearts constant, the enumeration member Suit.Hearts is referred to by its full name because the constant doesn’t have an explicit type specified. Inside the switch, the enumeration is referred to by the abbreviated form .Hearts because the value of self is already known to be a suit. You can use the abbreviated form anytime the value’s type is already known.

注意,上面提到的枚举的Hearts成员的两种方式:
当给hearts常量赋值的时候,枚举成员Suit.Hearts被列出全名,由于常量没有被显式的指定类型。在switch中。枚举被简写成.Hearts由于self的值已经知道是Suit类型。你能够使用缩写形式在不论什么值类型已知的情况下。


Use struct to create a structure. Structures support many of the same behaviors as classes, including methods and initializers. One of the most important differences between structures and classes is that structures are always copied when they are passed around in your code, but classes are passed by reference.
使用struct来创建一个结构体。

结构体同类一样支持非常多的行为,包含方法和构造器。结构体和类的一个最大的差别在于当结构体被调用到你的代码时。他们都是复制过来的,而类仅仅是传递引用。


struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The (rank.simpleDescription()) of (suit.simpleDescription())"
    }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

EXPERIMENT
实验

Add a method to Card that creates a full deck of cards, with one card of each combination of rank and suit.
加入一个方法到Card来创建一个全套的卡牌,用一套全花色的卡牌。(这里扑克牌和花色这里翻译不好)

An instance of an enumeration member can have values associated with the instance. Instances of the same enumeration member can have different values associated with them. You provide the associated values when you create the instance. Associated values and raw values are different: The raw value of an enumeration member is the same for all of its instances, and you provide the raw value when you define the enumeration.
一个枚举成员的实例能够有一个与实例相关联的值。这些同样的枚举成员的实例已经有了不同的值赋给他们。

当你创建这个实例时提供相关值。相关值和初始值是不同的。一个枚举成员的初始值对于全部它的实例都是同样的。而且是你在定义这个枚举类型时提供的。


For example, consider the case of requesting the sunrise and sunset time from a server. The server either responds with the information or it responds with some error information.
比如,考虑从server请求的日出和日落时间的情况。server响应信息回应一些错误信息

enum ServerResponse {
    case Result(String, String)
    case Error(String)
}
 
let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")
 
switch success {
case let .Result(sunrise, sunset):
    let serverResponse = "Sunrise is at (sunrise) and sunset is at (sunset)."
case let .Error(error):
    let serverResponse = "Failure...  (error)"
}

EXPERIMENT
实验

Add a third case to ServerResponse and to the switch.
加入第三个分支给ServerResponse,并使用。


Notice how the sunrise and sunset times are extracted from the ServerResponse value as part of matching the value against the switch cases.
注意,日落和日出时间是怎样从匹配switch case的一部分ServerResponse的值中获取的。

Protocols and Extensions

协议和拓展

Use protocol to declare a protocol.
使用protocol来声明一个协议。

protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}

Classes, enumerations, and structs can all adopt protocols.
类。枚举,和结构体都能够使用协议。


class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
 
struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription

EXPERIMENT
实验

Write an enumeration that conforms to this protocol.
写一个符合本协议的枚举。


Notice the use of the mutating keyword in the declaration of SimpleStructure to mark a method that modifies the structure. The declaration of SimpleClass doesn’t need any of its methods marked as mutating because methods on a class can always modify the class.
注意,mutatingkeyword的使用为了声明在SimpleStructure中改动了这种方法。SimpleClass不须要声明它的不论什么一种方法的变化由于类中的方法始终能够改动类。


Use extension to add functionality to an existing type, such as new methods and computed properties. You can use an extension to add protocol conformance to a type that is declared elsewhere, or even to a type that you imported from a library or framework.
使用extension来加入一个功能给已经存在的类型,就像新的方法和计算性能。你能够使用一个拓展去加入一个一致性的协议对于不论什么一种情况,甚至是你从一个库或框架导入进来的一个类型。

extension Int: ExampleProtocol {
    var simpleDescription: String {
    return "The number (self)"
    }
    mutating func adjust() {
        self += 42
    }
}
7.simpleDescription

Write an extension for the Double type that adds an absoluteValue property.
给Double类型写一个拓展。加入一个absoluteValue属性。

You can use a protocol name just like any other named type—for example, to create a collection of objects that have different types but that all conform to a single protocol. When you work with values whose type is a protocol type, methods outside the protocol definition are not available.
你能够像其它不论什么一种命名类型一样使用一个协议名称,比如,创建一个有不同类型的对象的集合。可是这些对象都符合单一的协议。

当你使用一种被定义为协议类型的类型的值时,那么定义在协议外面的方法将不可用。


let protocolValue: ExampleProtocol = a
protocolValue.simpleDescription
// protocolValue.anotherProperty  // Uncomment to see the error

Even though the variable protocolValue has a runtime type of SimpleClass, the compiler treats it as the given type of ExampleProtocol. This means that you can’t accidentally access methods or properties that the class implements in addition to its protocol conformance.
虽然变量protocolValue在SimpleClass中有一个可变类型,编译器将把它的类型给定为ExampleProtocol。这意味着你不能意外的訪问到除了类实现的一致的协议之外的方法和属性。

Generics

泛型

Write a name inside angle brackets to make a generic function or type.
在尖括号中写一个名字来定义一种泛型函数或类型。
func repeat<ItemType>(item: ItemType, times: Int) -> ItemType[] {
    var result = ItemType[]()
    for i in 0..times {
        result += item
    }
    return result
}
repeat("knock", 4)

You can make generic forms of functions and methods, as well as classes, enumerations, and structures.
你能够想类,枚举和结构体那样,定义一个方法和函数的泛型形式。

// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
    case None
    case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)

Use where after the type name to specify a list of requirements—for example, to require the type to implement a protocol, to require two types to be the same, or to require a class to have a particular superclass.
在类型名称后面加上where来指定一系列的需求。比如,或要求一个类型实现一个协议,或要求两个类型必须同样,或要求一个类有一个特别的基类。

func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.Element> (lhs: T, rhs: U) -> Bool {
    for lhsItem in lhs {
        for rhsItem in rhs {
            if lhsItem == rhsItem {
                return true
            }
        }
    }
    return false
}
anyCommonElements([1, 2, 3], [3])

EXPERIMENT
实验

Modify the anyCommonElements function to make a function that returns an array of the elements that any two sequences have in common.
改动anyCommonElements函数使得函数返回元素的数组为普通的有随意两列的数组。


In the simple cases, you can omit where and simply write the protocol or class name after a colon. Writing<T: Equatable> is the same as writing <T where T: Equatable>.
在简单的情况下,你能够省略where,仅仅在冒号后面写协议或者类的名称。书写<T : Equatable>和<T where T : Equatable>是一样的。

The Basics
基本知识

Swift is a new programming language for iOS and OS X app development. Nonetheless, many parts of Swift will be familiar from your experience of developing in C and Objective-C.
swift是一个作为开发IOS和OS X应用开发的一款新语言。

虽然如此。swift的很多部分将会和你所掌握的C和Objective-C语言非常相似。


Swift provides its own versions of all fundamental C and Objective-C types, including Int for integers; Doubleand Float for floating-point values; Bool for Boolean values; and String for textual data. Swift also provides powerful versions of the two primary collection types, Array and Dictionary, as described in Collection Types.
swift提供了自己的全部C和Objective-C基本类型。包含Int来相应整数。Double和Float相应浮点值。

Bool相应Boolean值,和String相应文本数据。swift相同提供了强有力的版本号相应两个基本的集合类型。Array和Dictionary。


Like C, Swift uses variables to store and refer to values by an identifying name. Swift also makes extensive use of variables whose values cannot be changed. These are known as constants, and are much more powerful than constants in C. Constants are used throughout Swift to make code safer and clearer in intent when you work with values that do not need to change.
像C,通过一个识别名称来使用变量来存储和引用一个值。

swift相同广泛的使用那些不能被改变值的变量。这些被叫做常量,而且不在C中更加的强大。

当你使用一个值单并不须要改变它时,常量被贯穿始终使的代码更加的安全和干净。


In addition to familiar types, Swift introduces advanced types not found in Objective-C. These include tuples, which enable you to create and pass around groupings of values. Tuples can return multiple values from a function as a single compound value.
除了常见的类型,swift引进了Objective-C里没有的先进类型。这些包含能够使你建立和归类那些值的元组。

元组能够从一个函数中返回多个值就像一个单独的复合的值。


Swift also introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just classes. Optionals are safer and more expressive than nilpointers in Objective-C and are at the heart of many of Swift’s most powerful features.
swift还介绍了可选类型,能够处理一个缺省的类型。可选或者表示“这是一个值,它等价于XXX”或者表示“这里没有一个值”。可选就像在Objective-C使用一个nil型的指针,可是他们能够使随意类型,不不过类。可选比Objective-C中中得指向nil的指针更安全和更有表现力,他是swift最强大的功能的核心所在。


Optionals are an example of the fact that Swift is a type safe language. Swift helps you to be clear about the types of values your code can work with. If part of your code expects a String, type safety prevents you from passing it an Int by mistake. This enables you to catch and fix errors as early as possible in the development process.
自选能够看出swift是一个类型安全的语言。它帮助你去明白你代码中使用的值的类型。假设你的代码中存在String。类型安全的机制会帮助你防止把它当成一个Int使用。这能够帮助你在开发project中尽早的找到和修复错误。

原文地址:https://www.cnblogs.com/zhchoutai/p/7220580.html