Merge pull request #410 from DianQK/develop

update Methods
This commit is contained in:
梁杰
2015-07-05 22:07:22 +08:00
2 changed files with 85 additions and 92 deletions

View File

@ -51,14 +51,14 @@ Swift 的`String`和`Character`类型提供了一个快速的,兼容 Unicode
要创建一个空字符串作为初始值,可以将空的字符串字面量赋值给变量,也可以初始化一个新的`String`实例:
```
```swift
var emptyString = "" // 空字符串字面量
var anotherEmptyString = String() // 初始化方法
// 两个字符串均为空并等价。
```
您可以通过检查其`Boolean`类型的`isEmpty`属性来判断该字符串是否为空:
```
```swift
if emptyString.isEmpty {
print("Nothing to see here")
}
@ -70,7 +70,7 @@ if emptyString.isEmpty {
您可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改:
```
```swift
var variableString = "Horse"
variableString += " and carriage"
// variableString 现在为 "Horse and carriage"
@ -104,7 +104,7 @@ Swift 默认字符串拷贝的方式保证了在函数/方法中传递的是字
您可通过`for-in`循环来遍历字符串中的`characters`属性来获取每一个字符的值:
```
```swift
for character in "Dog!🐶".characters {
print(character)
}
@ -119,12 +119,12 @@ for-in 循环在 [For Loops](05_Control_Flow.html#for_loops) 中进行了详细
另外,通过标明一个`Character`类型并用字符字面量进行赋值,可以建立一个独立的字符常量或变量:
```
```swift
let exclamationMark: Charater = "!"
```
字符串可以通过传递一个值类型为`Charater`的数组作为自变量来初始化:
```
```swift
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
@ -136,7 +136,7 @@ print(catString)
字符串可以通过加法运算符(`+`)相加在一起(或称“连接”)创建一个新的字符串:
```
```swift
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
@ -145,7 +145,7 @@ var welcome = string1 + string2
您也可以通过加法赋值运算符 (`+=`) 将一个字符串添加到一个已经存在字符串变量上:
```
```swift
var instruction = "look over"
instruction += string2
// instruction 现在等于 "look over there"
@ -153,7 +153,7 @@ instruction += string2
您可以用`append`方法将一个字符附加到一个字符串变量的尾部:
```
```swift
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome 现在等于 "hello there!"
@ -169,7 +169,7 @@ welcome.append(exclamationMark)
字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。
您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中:
```
```swift
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message 是 "3 times 2.5 is 7.5"
@ -215,7 +215,7 @@ Unicode 标量是对应字符的唯一21位数字或者修饰符例如`U+0061
`wiseWords`常量包含了两个双引号;
`dollarSign``blackHeart``sparklingHeart`常量演示了三种不同格式的 Unicode 标量:
```
```swift
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imageination is more important than knowledge" - Enistein
let dollarSign = "\u{24}" // $, Unicode 标量 U+0024
@ -232,7 +232,7 @@ let sparklingHeart = "\u{1F496}" // 💖, Unicode 标量 U+1F496
在这两种情况中,字母 é 代表了一个单一的 Swift 的字符串,同时代表了一个可扩展的字形群。
在第一种情况,这个字形群包含一个单一标量;而在第二种情况,它是包含两个标量的字形群:
```
```swift
let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // e 后面加上 ́
// eAcute 是 é, combinedEAcute 是 é
@ -243,7 +243,7 @@ let combinedEAcute: Character = "\u{65}\u{301}" // e 后面加上 ́
Swift 都会表示为同一个单一的字符:
```
```swift
let precomposed: Character = "\u{D55C}" // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
// precomposed 是 한, decomposed 是 한
@ -251,7 +251,7 @@ let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
可拓展的字符群集可以使包围记号(例如`COMBINING ENCLOSING CIRCLE`或者`U+20DD`)的标量包围其他 Unicode 标量,作为一个单一的字符:
```
```swift
let enclosedEAcute: Character = "\u{E9}\u{20DD}"
// enclosedEAcute 是 é⃝
```
@ -259,7 +259,7 @@ let enclosedEAcute: Character = "\u{E9}\u{20DD}"
局部的指示符号的 Unicode 标量可以组合成一个单一的字符,例如 `REGIONAL INDICATOR SYMBOL LETTER U`(`U+1F1FA`)`REGIONAL INDICATOR SYMBOL LETTER S`(`U+1F1F8`)
```
```swift
let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
// regionalIndicatorForUS 是 🇺🇸
```
@ -270,7 +270,7 @@ let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
调用字符串的`count`属性,就可以获取一个字符串的字符数量:
```
```swift
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
// 打印输出:"unusualMenagerie has 40 characters"
@ -279,7 +279,7 @@ print("unusualMenagerie has \(unusualMenagerie.characters.count) characters")
注意在 Swift 中,使用可拓展的字符群集作为字符来连接或改变字符串时,并不一定会更改字符串的字符数量。
例如,如果你用四个字符的单词 cafe 初始化一个新的字符串,然后添加一个 `COMBINING ACTUE ACCENT`(`U+0301`)作为字符串的结尾。最终这个字符串的字符数量仍然是4因为第四个字符是 é ,而不是 e
```
```swift
var word = "cafe"
print("the number of characters in \(word) is \(word.characters.count)")
// 打印输出 "the number of characters in cafe is 4"
@ -305,7 +305,7 @@ print("the number of characters in \(word) is \(word.characters.count)")
通过调用`String.Index``predecessor()`方法,可以立即得到前面一个索引,调用`successor()`方法可以立即得到后面一个索引。任何一个字符串的索引都可以通过锁链作用的这些方法来获取另一个索引,也可以调用`advance(start:n:)`函数来获取。但如果尝试获取出界的字符串索引,就会抛出一个运行时错误。
你可以使用下标语法来访问字符在字符串的确切索引。尝试获取出界的字符串索引,仍然抛出一个运行时错误。
```
```swift
let greeting = "Guten Tag"
greeting[greeting.startIndex]
// G
@ -322,7 +322,7 @@ greeting.endIndex.successor() // 错误
使用`characters`属性的`indices`会创建一个包含全部索引的范围(`Range`),用来在一个字符串中访问分立的字符。
```
```swift
for index in greeting.characters.indices {
print("\(greeting[index]) ", appendNewline: false)
}
@ -333,7 +333,7 @@ for index in greeting.characters.indices {
### 插入和删除 (Inserting and Removing)
调用`insert(_:atIndex:)`方法可以在一个字符串的指定索引插入一个字符。
```
```swift
var welcome = "hello"
welcome.insert("!", atIndex: welcome.endIndex)
// welcome now 现在等于 "hello!"
@ -341,14 +341,14 @@ welcome.insert("!", atIndex: welcome.endIndex)
调用`splice(_:atIndex:)`方法可以在一个字符串的指定索引插入一个字符串。
```
```swift
welcome.splice(" there".characters, atIndex: welcome.endIndex.predecessor())
// welcome 现在等于 "hello there!"
```
调用`removeAtIndex(_:)`方法可以在一个字符串的指定索引删除一个字符。
```
```swift
welcome.removeAtIndex(welcome.endIndex.predecessor())
// welcome 现在等于 "hello there"
// 翻译的人解释:最后还有一个换行符,所以这里删除的是 !
@ -356,7 +356,7 @@ welcome.removeAtIndex(welcome.endIndex.predecessor())
调用`removeRange(_:)`方法可以在一个字符串的指定索引删除一个子字符串。
```
```swift
let range = advance(welcome.endIndex, -6)..<welcome.endIndex
welcome.removeRange(range)
// welcome 现在等于 "hello"
@ -372,7 +372,7 @@ Swift 提供了三种方式来比较文本值:字符串字符相等、前缀
### 字符串/字符相等 (String and Character Equality)
字符串/字符可以用等于操作符(`==`)和不等于操作符(`!=`),详细描述在 [Comparison Operators](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID70)
```
```swift
let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
@ -384,7 +384,7 @@ if quotation == sameQuotation {
如果两个字符串(或者两个字符)的可扩展的字形群集是标准相等的,那就认为它们是相等的。在这个情况下,即使可扩展的字形群集是有不同的 Unicode 标量构成的,只要它们有同样的语言意义和外观,就认为它们标准相等。
例如,`LATIN SMALL LETTER E WITH ACUTE`(`U+00E9`)就是标准相等于`LATIN SMALL LETTER E`(`U+0065`)后面加上`COMBINING ACUTE ACCENT`(`U+0301`)。这两个字符群集都有效的表示字符 é ,所以它们被认为是标准相等的:
```
```swift
// "Voulez-vous un café?" 使用 LATIN SMALL LETTER E WITH ACUTE
let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
// "Voulez-vous un café?" 使用 LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
@ -397,7 +397,7 @@ if eAcuteQuestion == combinedEAcuteQuestion {
相反,英语中的`LATIN CAPITAL LETTER A`(`U+0401`,或者`A`)不等于俄语中的`CYRILLIC CAPITAL LETTER A`(`U+0410`,或者`A`)。两个字符看着是一样的,但却有不同的语言意义:
```
```swift
let latinCapitalLetterA: Character = "\u{41}"
let cyrillicCapitalLetterA: Character = "\u{0410}"
if latinCapitalLetterA != cyrillicCapitalLetterA {
@ -416,7 +416,7 @@ if latinCapitalLetterA != cyrillicCapitalLetterA {
通过调用字符串的`hasPrefix(_:)`/`hasSuffix(_:)`方法来检查字符串是否拥有特定前缀/后缀,两个方法均需要以字符串作为参数传入并传出`Boolean`值。
下面的例子以一个字符串数组表示莎士比亚话剧《罗密欧与朱丽叶》中前两场的场景位置:
```
```swift
let romeoAndJuliet = [
"Act 1 Scene 1: Verona, A public place",
"Act 1 Scene 2: Capulet's mansion",
@ -434,7 +434,7 @@ let romeoAndJuliet = [
您可以调用`hasPrefix(_:)`方法来计算话剧中第一幕的场景数:
```
```swift
var act1SceneCount = 0
for scene in romeoAndJuliet {
if scene.hasPrefix("Act 1 ") {
@ -447,7 +447,7 @@ print("There are \(act1SceneCount) scenes in Act 1")
相似地,您可以用`hasSuffix(_:)`方法来计算发生在不同地方的场景数:
```
```swift
var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
@ -481,7 +481,7 @@ Swift 提供了几种不同的方式来访问字符串的 Unicode 表示形式
下面由`D``o``g```(`DOUBLE EXCLAMATION MARK`, Unicode 标量 `U+203C`)`🐶`(`DOG FACE`Unicode 标量为`U+1F436`)组成的字符串中的每一个字符代表着一种不同的表示:
```
```swift
let dogString = "Dog‼🐶"
```
@ -532,7 +532,7 @@ let dogString = "Dog‼🐶"
</center>
</body>
```
```swift
for codeUnit in dogString.utf8 {
print("\(codeUnit) ", appendNewline: false)
}
@ -584,7 +584,7 @@ print("")
</body>
```
```swift
for codeUnit in dogString.utf16 {
print("\(codeUnit) ", appendNewline: false)
}
@ -638,7 +638,7 @@ print("")
</body>
```
```swift
for scalar in dogString.unicodeScalars {
print("\(scalar.value) ", appendNewline: false)
}
@ -652,7 +652,7 @@ print("")
作为查询字符值属性的一种替代方法,每个`UnicodeScalar`值也可以用来构建一个新的字符串值,比如在字符串插值中使用:
```
```swift
for scalar in dogString.unicodeScalars {
print("\(scalar) ")
}

View File

@ -14,19 +14,19 @@
结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一。在 Objective-C 中,类是唯一能定义方法的类型。但在 Swift 中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活的在你创建的类型(类/结构体/枚举)上定义方法。
<a name="instance_methods"></a>
## 实例方法(Instance Methods)
## 实例方法 (Instance Methods)
**实例方法**是属于某个特定类、结构体或者枚举类型实例的方法。实例方法提供访问和修改实例属性的方法或提供与实例目的相关的功能,并以此来支撑实例的功能。实例方法的语法与函数完全一致,详情参见[函数](../charpter2/06_Functions.md)。
实例方法要写在它所属的类型的前后大括号之间。实例方法能够隐式访问它所属类型的所有的其他实例方法和属性。实例方法只能被它所属的类的某个特定实例调用。实例方法不能脱离于现存的实例而被调用。
下面的例子,定义一个很简单的`Counter``Counter`能被用来对一个动作发生的次数进行计数:
下面的例子,定义一个很简单的`Counter``Counter`能被用来对一个动作发生的次数进行计数:
```swift
class Counter {
var count = 0
func increment() {
count++
++count
}
func incrementBy(amount: Int) {
count += amount
@ -60,13 +60,13 @@ class Counter {
<a name="local_and_external_parameter"></a>
### 方法的局部参数名称和外部参数名称(Local and External Parameter Names for Methods)
函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用),详情参见[函数的外部参数名](06_Functions.html)。方法参数也一样(因为方法就是函数,只是这个函数与某个类型相关联了)。但是,方法和函数的局部名称和外部名称的默认行为是不一样的。
函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用),详情参见[函数的外部参数名](06_Functions.html)。方法参数也一样(因为方法就是函数,只是这个函数与某个类型相关联了)。
Swift 中的方法和 Objective-C 中的方法极其相似。像在 Objective-C 中一样Swift 中方法的名称通常用一个介词指向方法的第一个参数,比如:`with``for``by`等等。前面的`Counter`类的例子中`incrementBy`方法就是这样的。介词的使用让方法在被调用时能像一个句子一样被解读。和函数参数不同对于方法的参数Swift 使用不同的默认处理方式,这可以让方法命名规范更容易写。
Swift 中的方法和 Objective-C 中的方法极其相似。像在 Objective-C 中一样Swift 中方法的名称通常用一个介词指向方法的第一个参数,比如:`with``for``by`等等。前面的`Counter`类的例子中`incrementBy(_:)`方法就是这样的。介词的使用让方法在被调用时能像一个句子一样被解读。
具体来说Swift 默认仅给方法的第一个参数名称一个局部参数名称;默认同时给第二个和后续的参数名称局部参数名称和外部参数名称。这个约定与典型的命名和调用约定相适应,与你在写 Objective-C 的方法时很相似。这个约定还让表达式方法在调用时不需要再限定参数名称。
具体来说Swift 默认仅给方法的第一个参数名称一个局部参数名称默认同时给第二个和后续的参数名称局部参数名称和外部参数名称。这个约定与典型的命名和调用约定相适应,与你在写 Objective-C 的方法时很相似。这个约定还让表达式方法在调用时不需要再限定参数名称。
看看下面这个`Counter`的另一个版本(它定义了一个更复杂的`incrementBy`方法):
看看下面这个`Counter`的另一个版本(它定义了一个更复杂的`incrementBy(_:)`方法):
```swift
class Counter {
@ -77,35 +77,28 @@ class Counter {
}
```
`incrementBy`方法有两个参数: `amount``numberOfTimes`。默认情况下Swift 只把`amount`当作一个局部名称,但是把`numberOfTimes`即看作局部名称又看作外部名称。下面调用这个方法:
`incrementBy(_:numverOfTimes:)`方法有两个参数: `amount``numberOfTimes`。默认情况下Swift 只把`amount`当作一个局部名称,但是把`numberOfTimes`即看作局部名称又看作外部名称。下面调用这个方法:
```swift
let counter = Counter()
counter.incrementBy(5, numberOfTimes: 3)
// counter value is now 15
```
你不必为第一个参数值再定义一个外部变量名:因为从函数名`incrementBy`已经能很清楚地看出它的作用。但是第二个参数,就要被一个外部参数名称所限定,以便在方法被调用时明确它的作用。
这种默认的行为能够有效的处理方法method,类似于在参数`numberOfTimes`前写一个井号(`#`
```swift
func incrementBy(amount: Int, #numberOfTimes: Int) {
count += amount * numberOfTimes
}
// counter 的值现在是 15
```
你不必为第一个参数值再定义一个外部变量名:因为从函数名`incrementBy(_numberOfTimes:)`已经能很清楚地看出它的作用。但是第二个参数,就要被一个外部参数名称所限定,以便在方法被调用时明确它的作用。
这种默认行为使上面代码意味着:在 Swift 中定义方法使用了与 Objective-C 同样的语法风格,并且方法将以自然表达式的方式被调用。
<a name="modifying_external_parameter"></a>
<a name="modifying_external_parameter_name_behavior_for_methods"></a>
### 修改方法的外部参数名称(Modifying External Parameter Name Behavior for Methods)
有时为方法的第一个参数提供一个外部参数名称是非常有用的,尽管这不是默认的行为。你可以自己添加一个显式的外部名称或者用一个井号(`#`)作为第一个参数的前缀来把这个局部名称当作外部名称使用。
相反,如果你不想为方法的第二个及后续的参数提供一个外部名称,可以通过使用下划线(`_`)作为该参数的显式外部名称,这样做将覆盖默认行为。
<a name="self_property"></a>
## `self`属性(The self Property)
<a name="the_self_property"></a>
### self 属性(The self Property)
类型的每一个实例都有一个隐含属性叫做`self``self`完全等同于该实例本身。你可以在一个实例的实例方法中使用这个隐含的`self`属性来引用当前实例。
@ -132,14 +125,14 @@ struct Point {
}
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOfX(1.0) {
println("This point is to the right of the line where x == 1.0")
print("This point is to the right of the line where x == 1.0")
}
// 输出 "This point is to the right of the line where x == 1.0"这个点在x等于1.0这条线的右边)
// 打印输出: This point is to the right of the line where x == 1.0
```
如果不使用`self`前缀Swift 就认为两次使用的`x`都指的是名称为`x`的函数参数。
<a name="modifying_value_types"></a>
<a name="modifying_value_types_from_within_instance_methods"></a>
### 在实例方法中修改值类型(Modifying Value Types from Within Instance Methods)
结构体和枚举是**值类型**。一般情况下,值类型的属性不能在它的实例方法中被修改。
@ -158,21 +151,21 @@ struct Point {
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveByX(2.0, y: 3.0)
println("The point is now at (\(somePoint.x), \(somePoint.y))")
// 输出 "The point is now at (3.0, 4.0)"
print("The point is now at (\(somePoint.x), \(somePoint.y))")
// 打印输出: "The point is now at (3.0, 4.0)"
```
上面的`Point`结构体定义了一个变异方法mutating method`moveByX``moveByX`用来移动点。`moveByX`方法在被调用时修改了这个点,而不是返回一个新的点。方法定义时加上`mutating`关键字,这才让方法可以修改值类型的属性。
上面的`Point`结构体定义了一个变异方法mutating method`moveByX(_:y:)`用来移动点。`moveByX`方法在被调用时修改了这个点,而不是返回一个新的点。方法定义时加上`mutating`关键字这才让方法可以修改值类型的属性。
注意:不能在结构体类型常量上调用变异方法,因为常量的属性不能被改变,即使想改变的是常量的变量属性也不行,详情参见[存储属性和实例变量](10_Properties.html#global_and_local_variables)
注意:不能在结构体类型常量上调用变异方法,因为常量的属性不能被改变,即使想改变的是常量的变量属性也不行,详情参见[存储属性和实例变量](10_Properties.html#global_and_local_variables)
```swift
let fixedPoint = Point(x: 3.0, y: 3.0)
fixedPoint.moveByX(2.0, y: 3.0)
// this will report an error
// 这里将会抛出一个错误
```
<a name="mutating_method_self"></a>
<a name="assigning_to_self_within_a_mutating_method"></a>
### 在变异方法中给self赋值(Assigning to self Within a Mutating Method)
变异方法能够赋给隐含属性`self`一个全新的实例。上面`Point`的例子可以用下面的方式改写:
@ -186,7 +179,7 @@ struct Point {
}
```
新版的变异方法`moveByX`创建了一个新的结构(它的 x 和 y 的值都被设定为目标值)。调用这个版本的方法和调用上个版本的最终结果是一样的。
新版的变异方法`moveByX(_:y:)`创建了一个新的结构(它的 x 和 y 的值都被设定为目标值)。调用这个版本的方法和调用上个版本的最终结果是一样的。
枚举的变异方法可以把`self`设置为相同的枚举类型中不同的成员:
@ -214,9 +207,9 @@ ovenLight.next()
上面的例子中定义了一个三态开关的枚举。每次调用`next`方法时,开关在不同的电源状态(`Off``Low``High`)之前循环切换。
<a name="type_methods"></a>
## 类型方法(Type Methods)
## 类型方法 (Type Methods)
实例方法是被类型的某个实例调用的方法。你也可以定义类型本身调用的方法,这种方法就叫做**类型方法**。声明类的类型方法,在方法的`func`关键字之前加上关键字`class`;声明结构体和枚举的类型方法,在方法的`func`关键字之前加上关键字`static`
实例方法是被类型的某个实例调用的方法。你也可以定义类型本身调用的方法,这种方法就叫做**类型方法**。声明结构体和枚举的类型方法,在方法的`func`关键字之前加上关键字`static`类可能会用关键字`Class`来允许子类重写父类的实现方法。
> 注意:
> 在 Objective-C 里面,你只能为 Objective-C 的类定义类型方法type-level methods。在 Swift 中,你可以为所有的类、结构体和枚举定义类型方法:每一个类型方法都被它所支持的类型显式包含。
@ -242,22 +235,22 @@ SomeClass.someTypeMethod()
```swift
struct LevelTracker {
static var highestUnlockedLevel = 1
static func unlockLevel(level: Int) {
if level > highestUnlockedLevel { highestUnlockedLevel = level }
}
static func levelIsUnlocked(level: Int) -> Bool {
return level <= highestUnlockedLevel
}
var currentLevel = 1
mutating func advanceToLevel(level: Int) -> Bool {
if LevelTracker.levelIsUnlocked(level) {
currentLevel = level
return true
} else {
return false
static var highestUnlockedLevel = 1
static func unlockLevel(level: Int) {
if level > highestUnlockedLevel { highestUnlockedLevel = level }
}
static func levelIsUnlocked(level: Int) -> Bool {
return level <= highestUnlockedLevel
}
var currentLevel = 1
mutating func advanceToLevel(level: Int) -> Bool {
if LevelTracker.levelIsUnlocked(level) {
currentLevel = level
return true
} else {
return false
}
}
}
}
```
@ -285,25 +278,25 @@ class Player {
}
```
`Player`类创建一个新的`LevelTracker`实例来监测这个用户的发展进度。它提供了`completedLevel`方法:一旦玩家完成某个指定等级就调用它。这个方法为所有玩家解锁下一等级,并且将当前玩家的进度更新为下一等级。(我们忽略了`advanceToLevel`返回的布尔值,因为之前调用`LevelTracker.unlockLevel`时就知道了这个等级已经被解锁了)。
`Player`类创建一个新的`LevelTracker`实例来监测这个用户的进度。它提供了`completedLevel`方法:一旦玩家完成某个指定等级就调用它。这个方法为所有玩家解锁下一等级,并且将当前玩家的进度更新为下一等级。(我们忽略了`advanceToLevel`返回的布尔值,因为之前调用`LevelTracker.unlockLevel`时就知道了这个等级已经被解锁了)。
你还可以为一个新的玩家创建一个`Player`的实例,然后看这个玩家完成等级一时发生了什么:
```swift
var player = Player(name: "Argyrios")
player.completedLevel(1)
println("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
// 输出 "highest unlocked level is now 2"最高等级现在是2
print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
// 打印输出:highest unlocked level is now 2
```
如果你创建了第二个玩家,并尝试让开始一个没有被任何玩家解锁的等级,那么这次设置玩家当前等级的尝试将会失败:
如果你创建了第二个玩家,并尝试让开始一个没有被任何玩家解锁的等级,那么这次设置玩家当前等级的尝试将会失败:
```swift
player = Player(name: "Beto")
if player.tracker.advanceToLevel(6) {
println("player is now on level 6")
print("player is now on level 6")
} else {
println("level 6 has not yet been unlocked")
print("level 6 has not yet been unlocked")
}
// 输出 "level 6 has not yet been unlocked"等级6还没被解锁
// 打印输出:level 6 has not yet been unlocked
```