使用 cocoa 现有的一些设计模式,是帮助开发者开发一款拥有合理设计思路、稳定的性能、良好的可扩展性应用的有效方法之一。这些模式都依赖于在 objective-c 中定义的类。因为 swift 与 objective-c 的互用性,所以你依然可以在 swift 代码中使用这些设计模式。在一些情况下,你甚至可以使用 swift 语言的特性扩展或简化这些 cocoa 设计模式,使这些设计模式更强大、更易于使用。
委托(delegation)
在 swift 和 objective-c 中,委托通常由一个定义交互方法和遵循规范的委托属性的协议表示。与 objective-c 相比,当你在 swift 中继承一个委托时,虽然继承模式不变,但是内部的实现已经改变了。就像在 objective-c 中,在你向委托发送消息之前,不管它是不是 nil 你都会去查看,如果定义的方法是非必须实现的方法,不管委托有没有实现这个方法,你也都会去查看。而在 swift 中,通过保持类型安全的特性,可以有效的消除这些繁琐、不必要的行为问题。
下面列出的代码可以说明这个过程:
1.检查 mydelegate 不为 nil。
2.检查 mydelegate 是否实现了继承的 window:willusefullscreencontentsize: 方法。
3.如果mydelegate 不为 nil 并且实现了 window:willusefullscreencontentsize: 方法4.那么调用该方法,将该方法的返回值分配给名为 fullscreensize 的属性。
将该方法的返回值输出在控制台。
// @inteface myobject : nsobject
// @property (nonatomic, weak) id
// @end
if let fullscreensize = mydelegate?.window?(mywindow, willusefullscreencontentsize: mysize) {
println(nsstringfromsize(fullscreensize))
}
注意: 在一个完全使用 swift 编写的 app 中,在定义 delegate 属性时,它作为一个不定值的 nswindowdelegate 对象,并将初始值设为 nil。
延迟初始化(lazy initialization)
你可以在 lazy stored properties 中了解到更多关于延迟初始化的信息。
错误报告(error reporting)
swift 中的错误报告模式沿用了 objective-c 的模式,但 swift 中不定值返回值的新特性给我们带来了额外的好处。举个很简单的例子,你用 bool 值作为一个函数的返回值,用于标识该函数是否执行成功,当你需要输出错误信息时,你可以在函数中添加一个nserrorpointer 类型的输出参数 nserror。这个类型类似 objective-c 中的 nserror **,并增加了内存安全性和非强制性的传参。你可以使用 & 运算符作为前缀引用一个不定值 nserror 类型作为 nserrorpointer 对象传递错误信息。如下面的代码所示:
var writeerror : nserror?
let written = mystring.writetofile(path, atomically: false,
encoding: nsutf8stringencoding,
error: &writeerror)
if !written {
if let error = writeerror {
println("write failure: \(error.localizeddescription)")
}
}
当你实现自己的方法时,你需要配置一个 nserrorpointer 对象,并将 nserrorpointer 对象的 memory 属性设为你创建的nserror 对象。首先检查调用者传递的参数,确保它是一个非 nil 的 nserror 对象。
复制纯文本新窗口
func contentsfortype(typename: string! error: nserrorpointer) -> anyobject! {
if cannotproducecontentsfortype(typename) {
if error {
error.memory = nserror(domain: domain, code: code, userinfo: [:])
}
return nil
}
// ...
}
target-action模式(target-action)
当有特定事件发生,需要一个对象向另一个对象发送消息时,我们通常采用 cocoa 的 target-action 设计模式。swift 和 objective-c 中的 target-action 模型基本类似。在 swift 中,你可以使用 selector 类型达到 objective-c 中 selectors 的效果。请在objective-c selectors 中查看在 swift 中使用 target-action 设计模式的示例。
类型匹配与统一规范(introspection)
在 objective-c 中,你可以使用 iskindofclass: 方法检查某个对象是否是指定类型,可以使用 conformstoprotocol: 方法检查某个对象是否遵循特定协议的规范。在 swift 中,你可以使用 is 运算符完成上述的功能,或者也可以使用 as? 向下匹配指定类型。
你可以使用 is 运算符检查一个实例是否是指定的子类。如果该实例是指定的子类,那么 is 运算结果为 true,反之为false。
if object is uibutton {
// object is of type uibutton
} else {
// object is not of type uibutton
}
你也可以使用 as? 运算符尝试向下匹配子类型,as? 运算符返回不定值,结合 if-let 语句使用。
if let button = object as? uibutton {
// object is successfully cast to type uibutton and bound to button
} else {
// object could not be cast to type uibutton
}
请在 type casting 中查看更多信息。
检查匹配协议的语法与检查匹配类的语法是一样的,下面是使用 as? 检查匹配协议的示例:
if let datasource = object as? uitableviewdatasource {
// object conforms to uitableviewdatasource and is bound to datasource
} else {
// object not conform to uitableviewdatasource
}
注意,当做完匹配之后,datasource 会转换为 uitableviewdatasource 类型,所以你只能访问和调用uitableviewdatasource 协议定义的属性和方法。当你想进行其他操作时,必须将其转换为其他的类型。
可以在 protocols 查看更多相关信息。