Merge branch 'gh-pages' of github.com:numbbbbb/the-swift-programming-language-in-chinese into gh-pages
This commit is contained in:
@ -9,10 +9,10 @@
|
||||
> 翻译+校对:[DianQK](https://github.com/DianQK)
|
||||
|
||||
> 2.1
|
||||
> 翻译:[DianQK](https://github.com/DianQK),[Realank](https://github.com/Realank) 校对:[shanks](http://codebuild.me),2016-01-18
|
||||
>
|
||||
> 2.2
|
||||
> 校对:[SketchK](https://github.com/SketchK) 2016-05-13
|
||||
> 翻译:[DianQK](https://github.com/DianQK),[Realank](https://github.com/Realank) 校对:[shanks](http://codebuild.me),2016-01-18
|
||||
>
|
||||
> 2.2
|
||||
> 校对:[SketchK](https://github.com/SketchK) 2016-05-13
|
||||
> 3.0.1,shanks,2016-11-13
|
||||
|
||||
本页包含内容:
|
||||
@ -34,17 +34,17 @@
|
||||
下面的例子,定义一个很简单的`Counter`类,`Counter`能被用来对一个动作发生的次数进行计数:
|
||||
|
||||
```swift
|
||||
class Counter {
|
||||
var count = 0
|
||||
func increment() {
|
||||
count += 1
|
||||
}
|
||||
func increment(by amount: Int) {
|
||||
count += amount
|
||||
}
|
||||
func reset() {
|
||||
count = 0
|
||||
}
|
||||
class Counter {
|
||||
var count = 0
|
||||
func increment() {
|
||||
count += 1
|
||||
}
|
||||
func increment(by amount: Int) {
|
||||
count += amount
|
||||
}
|
||||
func reset() {
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -62,15 +62,15 @@ let counter = Counter()
|
||||
// 初始计数值是0
|
||||
counter.increment()
|
||||
// 计数值现在是1
|
||||
counter.increment(by: 5)
|
||||
counter.increment(by: 5)
|
||||
// 计数值现在是6
|
||||
counter.reset()
|
||||
// 计数值现在是0
|
||||
```
|
||||
|
||||
函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用),详情参见[指定外部参数名](./06_Functions.html#specifying_external_parameter_names)。方法参数也一样,因为方法就是函数,只是这个函数与某个类型相关联了。
|
||||
|
||||
|
||||
函数参数可以同时有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用),详情参见[指定外部参数名](./06_Functions.html#specifying_external_parameter_names)。方法参数也一样,因为方法就是函数,只是这个函数与某个类型相关联了。
|
||||
|
||||
|
||||
<a name="the_self_property"></a>
|
||||
### self 属性
|
||||
|
||||
@ -104,8 +104,8 @@ if somePoint.isToTheRightOfX(1.0) {
|
||||
// 打印 "This point is to the right of the line where x == 1.0"
|
||||
```
|
||||
|
||||
如果不使用`self`前缀,Swift 就认为两次使用的`x`都指的是名称为`x`的函数参数。
|
||||
|
||||
如果不使用`self`前缀,Swift 就认为两次使用的`x`都指的是名称为`x`的函数参数。
|
||||
|
||||
<a name="modifying_value_types_from_within_instance_methods"></a>
|
||||
### 在实例方法中修改值类型
|
||||
|
||||
@ -137,19 +137,19 @@ print("The point is now at (\(somePoint.x), \(somePoint.y))")
|
||||
let fixedPoint = Point(x: 3.0, y: 3.0)
|
||||
fixedPoint.moveByX(2.0, y: 3.0)
|
||||
// 这里将会报告一个错误
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
<a name="assigning_to_self_within_a_mutating_method"></a>
|
||||
### 在可变方法中给 self 赋值
|
||||
|
||||
可变方法能够赋给隐含属性`self`一个全新的实例。上面`Point`的例子可以用下面的方式改写:
|
||||
|
||||
```swift
|
||||
struct Point {
|
||||
var x = 0.0, y = 0.0
|
||||
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
|
||||
self = Point(x: x + deltaX, y: y + deltaY)
|
||||
}
|
||||
struct Point {
|
||||
var x = 0.0, y = 0.0
|
||||
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
|
||||
self = Point(x: x + deltaX, y: y + deltaY)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -162,12 +162,12 @@ enum TriStateSwitch {
|
||||
case Off, Low, High
|
||||
mutating func next() {
|
||||
switch self {
|
||||
case Off:
|
||||
self = Low
|
||||
case Low:
|
||||
self = High
|
||||
case High:
|
||||
self = Off
|
||||
case .Off:
|
||||
self = .Low
|
||||
case .Low:
|
||||
self = .High
|
||||
case .High:
|
||||
self = .Off
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,27 +208,27 @@ SomeClass.someTypeMethod()
|
||||
游戏初始时,所有的游戏等级(除了等级 1)都被锁定。每次有玩家完成一个等级,这个等级就对这个设备上的所有玩家解锁。`LevelTracker`结构体用类型属性和方法监测游戏的哪个等级已经被解锁。它还监测每个玩家的当前等级。
|
||||
|
||||
```swift
|
||||
struct LevelTracker {
|
||||
static var highestUnlockedLevel = 1
|
||||
var currentLevel = 1
|
||||
|
||||
static func unlock(_ level: Int) {
|
||||
if level > highestUnlockedLevel { highestUnlockedLevel = level }
|
||||
}
|
||||
|
||||
static func isUnlocked(_ level: Int) -> Bool {
|
||||
return level <= highestUnlockedLevel
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
mutating func advance(to level: Int) -> Bool {
|
||||
if LevelTracker.isUnlocked(level) {
|
||||
currentLevel = level
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
struct LevelTracker {
|
||||
static var highestUnlockedLevel = 1
|
||||
var currentLevel = 1
|
||||
|
||||
static func unlock(_ level: Int) {
|
||||
if level > highestUnlockedLevel { highestUnlockedLevel = level }
|
||||
}
|
||||
|
||||
static func isUnlocked(_ level: Int) -> Bool {
|
||||
return level <= highestUnlockedLevel
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
mutating func advance(to level: Int) -> Bool {
|
||||
if LevelTracker.isUnlocked(level) {
|
||||
currentLevel = level
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -243,16 +243,16 @@ struct LevelTracker {
|
||||
下面,`Player`类使用`LevelTracker`来监测和更新每个玩家的发展进度:
|
||||
|
||||
```swift
|
||||
class Player {
|
||||
var tracker = LevelTracker()
|
||||
let playerName: String
|
||||
func complete(level: Int) {
|
||||
LevelTracker.unlock(level + 1)
|
||||
tracker.advance(to: level + 1)
|
||||
}
|
||||
init(name: String) {
|
||||
playerName = name
|
||||
}
|
||||
class Player {
|
||||
var tracker = LevelTracker()
|
||||
let playerName: String
|
||||
func complete(level: Int) {
|
||||
LevelTracker.unlock(level + 1)
|
||||
tracker.advance(to: level + 1)
|
||||
}
|
||||
init(name: String) {
|
||||
playerName = name
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -261,8 +261,8 @@ class Player {
|
||||
你还可以为一个新的玩家创建一个`Player`的实例,然后看这个玩家完成等级一时发生了什么:
|
||||
|
||||
```swift
|
||||
var player = Player(name: "Argyrios")
|
||||
player.complete(level: 1)
|
||||
var player = Player(name: "Argyrios")
|
||||
player.complete(level: 1)
|
||||
print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
|
||||
// 打印 "highest unlocked level is now 2"
|
||||
```
|
||||
@ -270,11 +270,11 @@ print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
|
||||
如果你创建了第二个玩家,并尝试让他开始一个没有被任何玩家解锁的等级,那么试图设置玩家当前等级将会失败:
|
||||
|
||||
```swift
|
||||
player = Player(name: "Beto")
|
||||
if player.tracker.advance(to: 6) {
|
||||
print("player is now on level 6")
|
||||
} else {
|
||||
print("level 6 has not yet been unlocked")
|
||||
player = Player(name: "Beto")
|
||||
if player.tracker.advance(to: 6) {
|
||||
print("player is now on level 6")
|
||||
} else {
|
||||
print("level 6 has not yet been unlocked")
|
||||
}
|
||||
// 打印 "level 6 has not yet been unlocked"
|
||||
```
|
||||
|
||||
@ -10,10 +10,10 @@
|
||||
|
||||
> 2.1
|
||||
> 翻译:[Channe](https://github.com/Channe)
|
||||
> 校对:[shanks](http://codebuild.me),[Realank](https://github.com/Realank) ,2016-01-23
|
||||
>
|
||||
> 2.2
|
||||
> 翻译+校对:[SketchK](https://github.com/SketchK) 2016-05-14
|
||||
> 校对:[shanks](http://codebuild.me),[Realank](https://github.com/Realank) ,2016-01-23
|
||||
>
|
||||
> 2.2
|
||||
> 翻译+校对:[SketchK](https://github.com/SketchK) 2016-05-14
|
||||
> 3.0.1,shanks,2016-11-13
|
||||
|
||||
本页包含内容:
|
||||
@ -189,26 +189,22 @@ unit4A = nil
|
||||
|
||||
Swift 提供了两种办法用来解决你在使用类的属性时所遇到的循环强引用问题:弱引用(weak reference)和无主引用(unowned reference)。
|
||||
|
||||
弱引用和无主引用允许循环引用中的一个实例引用而另外一个实例*不*保持强引用。这样实例能够互相引用而不产生循环强引用。
|
||||
|
||||
弱引用和无主引用允许循环引用中的一个实例引用而另外一个实例*不*保持强引用。这样实例能够互相引用而不产生循环强引用。
|
||||
|
||||
当其他的实例有更短的生命周期时,使用弱引用,也就是说,当其他实例析构在先时。在上面公寓的例子中,很显然一个公寓在它的生命周期内会在某个时间段没有它的主人,所以一个弱引用就加在公寓类里面,避免循环引用。相比之下,当其他实例有相同的或者更长生命周期时,请使用无主引用。
|
||||
|
||||
<a name="weak_references"></a>
|
||||
### 弱引用
|
||||
|
||||
*弱引用*不会对其引用的实例保持强引用,因而不会阻止 ARC 销毁被引用的实例。这个特性阻止了引用变为循环强引用。声明属性或者变量时,在前面加上`weak`关键字表明这是一个弱引用。
|
||||
|
||||
因为弱引用不会保持所引用的实例,即使引用存在,实例也有可能被销毁。因此,ARC 会在引用的实例被销毁后自动将其赋值为`nil`。并且因为弱引用可以允许它们的值在运行时被赋值为`nil`,所以它们会被定义为可选类型变量,而不是常量。
|
||||
|
||||
*弱引用*不会对其引用的实例保持强引用,因而不会阻止 ARC 销毁被引用的实例。这个特性阻止了引用变为循环强引用。声明属性或者变量时,在前面加上`weak`关键字表明这是一个弱引用。
|
||||
|
||||
因为弱引用不会保持所引用的实例,即使引用存在,实例也有可能被销毁。因此,ARC 会在引用的实例被销毁后自动将其赋值为`nil`。并且因为弱引用可以允许它们的值在运行时被赋值为`nil`,所以它们会被定义为可选类型变量,而不是常量。
|
||||
|
||||
你可以像其他可选值一样,检查弱引用的值是否存在,你将永远不会访问已销毁的实例的引用。
|
||||
|
||||
> 注意
|
||||
> 当 ARC 设置弱引用为`nil`时,属性观察不会被触发。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
下面的例子跟上面`Person`和`Apartment`的例子一致,但是有一个重要的区别。这一次,`Apartment`的`tenant`属性被声明为弱引用:
|
||||
|
||||
```swift
|
||||
@ -279,7 +275,7 @@ unit4A = nil
|
||||
无主引用通常都被期望拥有值。不过 ARC 无法在实例被销毁后将无主引用设为`nil`,因为非可选类型的变量不允许被赋值为`nil`。
|
||||
|
||||
> 重要
|
||||
> 使用无主引用,你*必须*确保引用始终指向一个未销毁的实例。
|
||||
> 使用无主引用,你*必须*确保引用始终指向一个未销毁的实例。
|
||||
> 如果你试图在实例被销毁后,访问该实例的无主引用,会触发运行时错误。
|
||||
|
||||
下面的例子定义了两个类,`Customer`和`CreditCard`,模拟了银行客户和客户的信用卡。这两个类中,每一个都将另外一个类的实例作为自身的属性。这种关系可能会造成循环强引用。
|
||||
@ -347,14 +343,11 @@ john = nil
|
||||
// 打印 ”Card #1234567890123456 is being deinitialized”
|
||||
```
|
||||
|
||||
最后的代码展示了在`john`变量被设为`nil`后`Customer`实例和`CreditCard`实例的构造函数都打印出了“销毁”的信息。
|
||||
|
||||
> 注意
|
||||
> The examples above show how to use safe unowned references. Swift also provides unsafe unowned references for cases where you need to disable runtime safety checks—for example, for performance reasons. As with all unsafe operations, you take on the responsiblity for checking that code for safety.
|
||||
以上例子展示如何使用一个安全的无主引用,Swift 也提供了*不安全*的无主引用,当你需要禁用运行时的安全检查时-举个例子
|
||||
You indicate an unsafe unowned reference by writing unowned(unsafe). If you try to access an unsafe unowned reference after the instance that it refers to is deallocated, your program will try to access the memory location where the instance used to be, which is an unsafe operation.
|
||||
|
||||
最后的代码展示了在`john`变量被设为`nil`后`Customer`实例和`CreditCard`实例的构造函数都打印出了“销毁”的信息。
|
||||
|
||||
> 注意
|
||||
>上面的例子展示了如何使用安全的无主引用。对于需要禁用运行时的安全检查的情况(例如,出于性能方面的原因),Swift还提供了不安全的无主引用。与所有不安全的操作一样,你需要负责检查代码以确保其安全性。
|
||||
>你可以通过`unowned(unsafe)`来声明不安全无主引用。如果你试图在实例被销毁后,访问该实例的不安全无主引用,你的程序会尝试访问该实例之前所在的内存地址,这是一个不安全的操作。
|
||||
|
||||
<a name="unowned_references_and_implicitly_unwrapped_optional_properties"></a>
|
||||
### 无主引用以及隐式解析可选属性
|
||||
|
||||
Reference in New Issue
Block a user