Cocoa 中已有的设计模式很有用,但这些模式很多依赖于 objc 的类。由于 objc 与 Swift 有着互操作性,所以也可以在 Swift 中使用这些通用的模式。
Delegation
Swift 使用代理的步骤:
- 检查
myDelegate
不为nil
- 检查
myDelegate
实现了方法window:willUseFullScreenContentSize:
- 如果 1 和 2 都为 ture,就调用方法,并把结果赋给
fullScreenSize
- 打印返回值
|
|
Lazy Initialization
在 objc 中的延迟初始化:
|
|
Swift 中对于存储型变量的延迟初始化可以用lazy
修饰:
|
|
由于在访问一个完全初始化的实例时,延迟属性才会计算,它可能在它的初始化表达式中访问常量或变量属性:
|
|
对于需要初始化之外的其他额外工作的值,可以将一个返回初始化值的闭包赋值给这个变量。
|
|
如果一个延迟属性还未初始化,并且同时被多个线程访问,那么不能保证它只被初始化一次。
Error Handling
在 objc 中,访问通过传递 NSError 指针值来获取错误信息。Swift 会将其自动转化为原生的错误处理方式。
|
|
|
|
Catching and Handling an Error
objc 中这么处理错误:
|
|
Swift 中等价的代码:
|
|
可以用catch
子句来匹配具体的错误:
|
|
Converting Errors to Optional Values
Swift 中,用try?
将抛出方法变为返回一个可选值,然后检查值是否为nil
。
|
|
|
|
Throwing an Error
发生错误时,objc 与 Swift 的做法:
|
|
|
|
如果 objc 调用了一个抛出错误的 Swift 方法,这个错误会自动变为 objc 方法中的错误指针参数。
|
|
如果这个方法抛出了错误,Swift 调用的话,错误会转移到调用方作用域;objc 调用的话,错误会变成指针参数。
objc 中如果不提供错误指针,错误就会被忽略,而 Swift 中调用抛出方法需要有显示的错误处理。
如果 objc 方法发生错误,Swift 无法处理,会触发一个运行时错误。所以 objc 中的错误必须在 objc 中处理。
Key-Value Observing
Swift 要使用 KVO,类必须继承 NSObject。步骤如下:
- 对于要观察的变量,使用
dynamic
修饰:
|
|
- 创建一个全局上下文变量:
|
|
- 添加一个观察者,重写
observeValue(for:of:change:context:)
方法,并且在deinit
中移除观察者:
|
|
Undo
在 app 的事件响应链中,UIResponder
的子类有一个只读属性undoManager
,NSUndoManager
维护着 app 的撤销栈。
NSUndoManager
提供两种方式来注册撤销操作:一种“简单撤销”,调用一个带有一个对象参数的选择子;另一个是“基于调用的撤销”,用一个NSInvocation
对象来接收任意的参数。
有一个Task
模型,ToDoListController
用它来展示任务列表:
|
|
对于接收多个参数的方法,可以用NSInvocation
来创建一个撤销操作。
|
|
prepare(withInvocationTarget:)
方法对于特定的target
返回一个代理。通过转换ToDoListController
,返回值可以直接进行对应的调用mark(task:asCompleted:)
。
Singleton
在 objc 中创建单例:
|
|
在 Swift 中,可以简单的用一个 static 类型的变量,它保证仅进行一次的延迟初始化,即使在多个线程中同时访问。
|
|
如果想要执行除了初始化的额外步骤,可以将闭包的执行结果复制给全局常量:
|
|
Introspection
Swift 中用is
操作符检查对象类型,as?
用来向下转换类型。
|
|
|
|
检查是否遵循或转换为某个协议的方法与类型的检查和转换相同:
|
|
Serializing
objc 中,可以用 Foundation 框架中的类NSJSONSerialiation
和NSPropertyListSerialization
从 JSON 或列表型的序列化值——通常是NSDictionary<NSString *, id>
中初始化对象。在 Swift 中相同,但它需要额外的类型转换。
如转换Venue
结构:
|
|
收到的 JSON 消息可能是这样:
|
|
待填坑…
Localization
待填坑…
Autorelease Pool
objc 中,autorelease pool 块用@autoreleasepool
标记。Swift 中,可以使用autoreleasepool(_:)
函数,在一个 autorelease pool 块中执行一个闭包。
|
|
API Availability
待填坑…
Processing Command-Line Arguments
通过访问CommandLine.arguments
,可以得到启动时命令行参数列表。
|
|
|
|
CommandLine.arguments
的第一个元素是可执行文件的路径,在启动时定义的命令行参数从CommandLine.arguments[1]
开始。