标签(空格分隔): Swift
此次更新内容
- 在(闭包一章的)添加了自动闭包(Autoclosures)一节,有@autoclosure属性的信息——还包括它的@autoclosure(escaping)形式。
- 给Optional Binding一节添加了一个例子:使用了where从句的多个可选绑定。
- 给String Literalsy一节添加了如下内容:使用“+”操作符在编译阶段是如何将字符字面值联系起来的。
- 给Metatype Type一节添加了如下内容:comparing Metatype values和在结构体的初始化表达式中使用它们。
- 给Debugging with Assertinons一节添加了一个NOTE:关于如果用户定义的断言不可用的情形。
更新详细
自动闭包
一个自动闭包 是一个被自动创建的闭包,它被包裹在一个表达式中,作为函数的参数被传递。它本身不带有任何的参数,当它被调用时,它会返回它所处的表达式的值。一个自动闭包能让你推迟执行某些代码,因为那部分代码只有你调用闭包的时候才会被执行。正是因为自动闭包能够让你控制什么时候执行其中的代码,所以正好适合那些有副作用或者执行起来颇费力气的代码。下面的代码展示了如何让一个闭包延迟执行。
var customersInLine = ["Chris","Alex","Ewa","Barry","Daniella"] let nextCustomer = { customersInLine.removeAtIndex(0) } print(customersInLine.count) // prints "5" print("Now serving \(nextCustomer())!") // prints "Now serving Chris!" print(customersInLine.count) // prints "4"
尽管在闭包中customersInLine数组的第一个元素被移除掉了,但是这个操作直到闭包被调用时才会真正执行。如果闭包没有被调用到,表达式中的闭包就永远不会被执行。这里要说明的是nextCustomer的类型不是String而是()->String——一个不带任何参数返回一个字符串的函数。用下面的一个函数,你可以做同样的事情:
// customersInLine is ["Alex","Daniella"] func serveNextCustomer(customer: () -> String) { print("Now serving \(customer())!") } serveNextCustomer( { customersInLine.removeAtIndex(0) } ) // prints "Now serving Alex!"
上面的serverNextCustomer(_:)函数的参数是一个返回下一个客户名字的闭包。下面这个版本的serverNextCustomer(_:)函数做了相同的事情,不同的是没有明确的采用闭包,而是通过给它的参数加@autoclosure标记使用了自动闭包。现在你可以在调用它的时候如同使用一个String,而非闭包。
// customersInLine is ["Ewa","Daniella"] func serveNextCustomer(@autoclosure customer: () -> String) { print("Now serving \(customer())!") } serveNextCustomer(customersInLine.removeAtIndex(0)) // prints "Now serving Ewa!"
NOTE
过度使用自动闭包会让你的代码难以被读懂。根据上下文和函数的名称能够让代码执行被推迟的目的更显而易见。
@autoclosure属性暗含了@noescape属性,它会标明那个闭包只能在特定的函数中使用。也就是说,那个闭包不允许被函数存储,不允许脱离那个函数的作用范围,不允许在那个函数返回后再执行闭包。如果你想要一个自动闭包可以脱离函数的作用范围,那么使用@autoclosure(escaping)标记:
// customersInLine is ["Barry","Daniella"] var customerClosures: [() -> String] = [] func collectCustomerClosures(@autoclosure(escaping) customer: () -> String) { customerClosures.append(customer) } collectCustomerClosures(customersInLine.removeAtIndex(0)) collectCustomerClosures(customersInLine.removeAtIndex(0)) print("Collected \(customerClosures.count) closures.") // prints "Collected 2 closures." for customerClosure in customerClosures { print("Now serving \(customerClosure())!") } // prints "Now serving Barry!" // prints "Now serving Daniella!"
上面的代码中,没有传递一个闭包作为customer参数,而是在collectCustomerClosures(_:)函数中将闭包追加到customerClosures数组中。customerClosures数组在函数的作用域之外定义,这就意味着其中的闭包可以在函数返回后被执行。因此,customer参数必须被允许在函数的作用域之外被执行。
更多的有关@autoclosure和@noescape的属性的信息,参见Declaration Attributes.
可选绑定可以使用where从句
可选绑定(Optional Binding)一节的末尾,说明可以在条语句中进行多个可选绑定,做了如下的修改:
原版内容:
单一的一条if语句中可以出现用逗号分隔的多个可选绑定。
if let constantName = someOptional,anotherConstantName = someOtherOptional { statements }
现在的内容:
单一的一条if语句中可以出现用分号分割的多个可选绑定,而且还可以使用一个where从句判断一个布尔条件:
if let firstNumber = Int("4"),secondNumber = Int("42") where firstNumber < secondNumber { print("\(firstNumber) < \(secondNumber)") } // prints "4 < 42"
使用断言调试时,断言失效的情况
在这一节的末尾添加了一个NOTE:
断言在代码经过优化编译后会失效,比如说在Xcode中采用一个app目标的默认发布设置进行构建时
关于Metatype Type的修改
由于没有原版本的内容记录,暂时没有做对比。