diff --git a/source/chapter2/23_Automatic_Reference_Counting.md b/source/chapter2/23_Automatic_Reference_Counting.md index 7c4192c2..597ff899 100755 --- a/source/chapter2/23_Automatic_Reference_Counting.md +++ b/source/chapter2/23_Automatic_Reference_Counting.md @@ -18,7 +18,7 @@ Swift 使用*自动引用计数(ARC)*机制来跟踪和管理你的应用程 然而,当 ARC 收回和释放了正在被使用中的实例,该实例的属性和方法将不能再被访问和调用。实际上,如果你试图访问这个实例,你的应用程序很可能会崩溃。 -为了确保使用中的实例不会被销毁,ARC 会跟踪和计算每一个实例正在被多少属性,常量和变量所引用。哪怕实例的引用数为1,ARC 都不会销毁这个实例。 +为了确保使用中的实例不会被销毁,ARC 会跟踪和计算每一个实例正在被多少属性,常量和变量所引用。哪怕实例的引用数为 1,ARC 都不会销毁这个实例。 为了使上述成为可能,无论你将实例赋值给属性、常量或变量,它们都会创建此实例的强引用。之所以称之为“强”引用,是因为它会将实例牢牢地保持住,只要强引用还在,实例是不允许被销毁的。 @@ -325,6 +325,7 @@ john = nil 最后的代码展示了在 `john` 变量被设为 `nil` 后 `Customer` 实例和 `CreditCard` 实例的析构器都打印出了“销毁”的信息。 > 注意 +> > 上面的例子展示了如何使用安全的无主引用。对于需要禁用运行时的安全检查的情况(例如,出于性能方面的原因),Swift 还提供了不安全的无主引用。与所有不安全的操作一样,你需要负责检查代码以确保其安全性。 > 你可以通过 `unowned(unsafe)` 来声明不安全无主引用。如果你试图在实例被销毁后,访问该实例的不安全无主引用,你的程序会尝试访问该实例之前所在的内存地址,这是一个不安全的操作。 @@ -502,7 +503,7 @@ lazy var someClosure: (Int, String) -> String = { 如果闭包没有指明参数列表或者返回类型,它们会通过上下文推断,那么可以把捕获列表和关键字 `in` 放在闭包最开始的地方: ```swift -lazy var someClosure: Void -> String = { +lazy var someClosure: () -> String = { [unowned self, weak delegate = self.delegate!] in // 这里是闭包的函数体 } @@ -527,7 +528,7 @@ class HTMLElement { let name: String let text: String? - lazy var asHTML: Void -> String = { + lazy var asHTML: () -> String = { [unowned self] in if let text = self.text { return "<\(self.name)>\(text)" diff --git a/source/chapter2/24_Memory_Safety.md b/source/chapter2/24_Memory_Safety.md index ef5239ee..aa8f36f5 100644 --- a/source/chapter2/24_Memory_Safety.md +++ b/source/chapter2/24_Memory_Safety.md @@ -34,7 +34,6 @@ print("We're number \(one)!") > 如果你曾经在单线程代码里有访问冲突,Swift 可以保证你在编译或者运行时会得到错误。对于多线程的代码,可以使用 [Thread Sanitizer](https://developer.apple.com/documentation/code_diagnostics/thread_sanitizer) 去帮助检测多线程的冲突。 - ### 内存访问性质 内存访问冲突时,要考虑内存访问上下文中的这三个性质:访问是读还是写,访问的时长,以及被访问的存储地址。特别是,冲突会发生在当你有两个访问符合下列的情况: @@ -67,7 +66,7 @@ print(myNumber) 一个函数会对它所有的 in-out 参数进行长期写访问。in-out 参数的写访问会在所有非 in-out 参数处理完之后开始,直到函数执行完毕为止。如果有多个 in-out 参数,则写访问开始的顺序与参数的顺序一致。 -长期访问的存在会造成一个结果,你不能在访问以 in-out 形式传入后的原变量,即使作用域原则和访问权限允许 —— 任何访问原变量的行为都会造成冲突。例如: +长期访问的存在会造成一个结果,你不能在访问以 in-out 形式传入后的原变量,即使作用域原则和访问权限允许——任何访问原变量的行为都会造成冲突。例如: ```swift var stepSize = 1 @@ -162,12 +161,11 @@ oscar.shareHealth(with: &oscar) // 错误:oscar 访问冲突 ``` -mutating 方法在调用期间需要对 `self` 发起写访问,而同时 in-out 参数也需要写访问。在方法里,`self` 和 `teammate` 都指向了同一个存储地址 —— 就像下面展示的那样。对于同一块内存同时进行两个写访问,并且它们重叠了,就此产生了冲突。 +mutating 方法在调用期间需要对 `self` 发起写访问,而同时 in-out 参数也需要写访问。在方法里,`self` 和 `teammate` 都指向了同一个存储地址——就像下面展示的那样。对于同一块内存同时进行两个写访问,并且它们重叠了,就此产生了冲突。 ![](https://docs.swift.org/swift-book/_images/memory_share_health_oscar_2x.png) - ## 属性的访问冲突 如结构体,元组和枚举的类型都是由多个独立的值组成的,例如结构体的属性或元组的元素。因为它们都是值类型,修改值的任何一部分都是对于整个值的修改,意味着其中一个属性的读或写访问都需要访问整一个值。例如,元组元素的写访问重叠会产生冲突: @@ -198,12 +196,10 @@ func someFunction() { 上面的例子里,`oscar` 的 `health` 和 `energy` 都作为 in-out 参数传入了 `balance(_:_:)` 里。编译器可以保证内存安全,因为两个存储属性任何情况下都不会相互影响。 -限制结构体属性的重叠访问对于保证内存安全不是必要的。保证内存安全是必要的,但因为访问独占权的要求比内存安全还要更严格 —— 意味着即使有些代码违反了访问独占权的原则,也是内存安全的,所以如果编译器可以保证这种非专属的访问是安全的,那 Swift 就会允许这种行为的代码运行。特别是当你遵循下面的原则时,它可以保证结构体属性的重叠访问是安全的: +限制结构体属性的重叠访问对于保证内存安全不是必要的。保证内存安全是必要的,但因为访问独占权的要求比内存安全还要更严格——意味着即使有些代码违反了访问独占权的原则,也是内存安全的,所以如果编译器可以保证这种非专属的访问是安全的,那 Swift 就会允许这种行为的代码运行。特别是当你遵循下面的原则时,它可以保证结构体属性的重叠访问是安全的: * 你访问的是实例的存储属性,而不是计算属性或类的属性 * 结构体是本地变量的值,而非全局变量 * 结构体要么没有被闭包捕获,要么只被非逃逸闭包捕获了 如果编译器无法保证访问的安全性,它就不会允许那次访问。 - - diff --git a/source/chapter2/25_Access_Control.md b/source/chapter2/25_Access_Control.md index a8e9a409..5254094d 100644 --- a/source/chapter2/25_Access_Control.md +++ b/source/chapter2/25_Access_Control.md @@ -81,7 +81,7 @@ Swift 中的访问级别遵循一个基本原则:*不可以在某个实体中 ## 访问控制语法 -通过修饰符 `open`,`public`,`internal`,`fileprivate`,`private` 来声明实体的访问级别: +通过修饰符 `open`、`public`、`internal`、`fileprivate`、`private` 来声明实体的访问级别: ```swift public class SomePublicClass {} @@ -135,8 +135,7 @@ fileprivate class SomeFilePrivateClass { // 显式 fileprivate 类 private class SomePrivateClass { // 显式 private 类 func somePrivateMethod() {} // 隐式 private 类成员 } - -```swift +``` ### 元组类型 @@ -208,7 +207,11 @@ public enum CompassPoint { ```swift public class A { +<<<<<<< HEAD private func someMethod() {} +======= + fileprivate func someMethod() {} +>>>>>>> /25_Access_Control 修正标点使用,更新代码 } internal class B: A { @@ -220,7 +223,7 @@ internal class B: A { ```swift public class A { - private func someMethod() {} + fileprivate func someMethod() {} } internal class B: A { @@ -370,7 +373,7 @@ Extension 可以在访问级别允许的情况下对类、结构体、枚举进 ```swift protocol SomeProtocol { - func doSomething() {} + func doSomething() } ``` diff --git a/source/chapter2/26_Advanced_Operators.md b/source/chapter2/26_Advanced_Operators.md index 7c54f6ce..88b48272 100644 --- a/source/chapter2/26_Advanced_Operators.md +++ b/source/chapter2/26_Advanced_Operators.md @@ -240,7 +240,7 @@ signedOverflow = signedOverflow &- 1 运算符的*优先级*使得一些运算符优先于其他运算符;它们会先被执行。 -*结合性*定义了相同优先级的运算符是如何结合的,也就是说,是与左边结合为一组,还是与右边结合为一组。可以将其理解为“它们是与左边的表达式结合的,”或者“它们是与右边的表达式结合的。” +*结合性*定义了相同优先级的运算符是如何结合的,也就是说,是与左边结合为一组,还是与右边结合为一组。可以将其理解为“它们是与左边的表达式结合的”,或者“它们是与右边的表达式结合的”。 当考虑一个复合表达式的计算顺序时,运算符的优先级和结合性是非常重要的。举例来说,运算符优先级解释了为什么下面这个表达式的运算结果会是 `17`。 @@ -424,7 +424,7 @@ let anotherTwoThreeFour = Vector3D(x: 2.0, y: 3.0, z: 4.0) if twoThreeFour == anotherTwoThreeFour { print("These two vectors are also equivalent.") } -// Prints "These two vectors are also equivalent." +// 打印“These two vectors are also equivalent.” ``` @@ -476,8 +476,8 @@ let plusMinusVector = firstVector +- secondVector // plusMinusVector 是一个 Vector2D 实例,并且它的值为 (4.0, -2.0) ``` -这个运算符把两个向量的 `x` 值相加,同时从第一个向量的 `y` 中减去第二个向量的 `y` 。因为它本质上是属于“相加型”运算符,所以将它放置在 `+` 和 `-` 等默认中缀“相加型”运算符相同的优先级组中。关于 Swift 标准库提供的运算符,以及完整的运算符优先级组和结合性设置,请参考 [运算符声明](https://developer.apple.com/documentation/swift/swift_standard_library/operator_declarations)。而更多关于优先级组以及自定义操作符和优先级组的语法,请参考[运算符声明](https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID380) +这个运算符把两个向量的 `x` 值相加,同时从第一个向量的 `y` 中减去第二个向量的 `y` 。因为它本质上是属于“相加型”运算符,所以将它放置在 `+` 和 `-` 等默认中缀“相加型”运算符相同的优先级组中。关于 Swift 标准库提供的运算符,以及完整的运算符优先级组和结合性设置,请参考 [运算符声明](https://developer.apple.com/documentation/swift/swift_standard_library/operator_declarations)。而更多关于优先级组以及自定义操作符和优先级组的语法,请参考[运算符声明](https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID380)。 > 注意 > -> 当定义前缀与后缀运算符的时候,我们并没有指定优先级。然而,如果对同一个值同时使用前缀与后缀运算符,则后缀运算符会先参与运算。 \ No newline at end of file +> 当定义前缀与后缀运算符的时候,我们并没有指定优先级。然而,如果对同一个值同时使用前缀与后缀运算符,则后缀运算符会先参与运算。