使用Swift与Cocoa和Objective-C交互-(5)采用 Cocoa 的设计模式



- 作者: SwiftCafe


采用 Cocoa 的设计模式

使用 Cocoa 已有的设计模式,可以帮助你建立良好设计,并且有弹性的 App。许多这些模式都依赖于定义在 Objective-C 中的类。因为 Swift 和 Objective-C 之间的互操作性,你可以在 Swift 中利用这些公用的模式。在很多案例中,你可以使用 Swift 的语言特性来扩展或简化现有的 Cocoa 设计模式,让他们更加强大并易于使用。

代理

在 Swift 和 Objective-C 中,代理通常都以协议的方式来表示。和 Objective-C 比起来,当你在 Swift 中实现代理时,设计模式还是相同的,但是实现方式改变了。就像 Objective-C,在你发消息给代理之前,你回检测它是否为 nil —— 还有这个方法是否为 Optional 的,你检查这个代理是否响应这个 selector。在 Swift 中,可以通过维护类型安全来解决这个问题。下面列出的代码描述了如下的过程:

  1. 检测 myDelegate 为非 nil。
  2. 检测 myDelegate 是否实现了 window:willUseFullScreenContentSize:
  3. 如果 1 和 2 的条件满足,那么调用这个方法并将返回值赋给 fullScreenSize 变量。
  4. 打印方法的返回值。
1
2
3
4
5
6
// @interface MyObject : NSObject
// @property (nonatomic, weak) id<NSWindowDelegate> delegate;
// @end
if let fullScreenSize = myDelegate?.window?(myWindow, willUseFullScreenContentSize: mySize) {
println(NSStringFromSize(fullScreenSize))
}

注意:
在一个纯 Swift 写的 App 中,输入 delegate 作为 Optional 对象 >NSWindowDelegate 的属性,并且为他赋初值 nil

懒加载

信息即将来临,你可以在 Swift 编程语言一书中,读到更多关于懒存储属性的内容。

错误报告

Swift 中的错误报告和 Objective-C 中的一样,并且附加上 Optional 返回值提供的附加特性。在最简单的例子中,你从函数中返回一个 Bool 类型的值来表示是否成功。当你需要报告错误的原因,你可以给函数添加一个 NSErrorPointer 类型的输出参数。这个类型类型几乎等于 Objective-C 的 NSError **类型,并且更加的内存安全和支持 Optional 类型。你可以通过对 Optional 的 NSError 类型添加 & 前缀操作符,就像下面的代码列出的那样:

1
2
3
4
5
6
7
8
9
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 对象。确保调用者首先传递了非 nilNSErrorPointer 对象。

1
2
3
4
5
6
7
8
9
func contentsForType(typeName: String!, error: NSErrorPointer) -> AnyObject! {
if cannotProduceContentsForType(typeName) {
if error {
error.memory = NSError(domain: domain, code: code, userInfo: [:])
}
return nil
}
// ...
}

Key-Value 检测

信息即将到来。

Target-Action

Target-action 是 Cocoa 一个公用的设计模式,用于当一个指定事件发生时,一个对象向另一个对象发送消息。这个 target-action 模型在 Swift 和 Objective-C 中基本相似。在 Swift 中,你可以使用 Selector 类型来引用 Objective-C 的 selector。关于在 Swift 中使用 target-action 的例子,可以查看 Objective-C Selector 这章。

内省

在 Objective-C 中,你使用 isKindOfClass: 来检测一个对象是否为某些类型,使用 conformsToProtocol: 方法来检测一个对象是否遵守一个特定协议。在 Swift 中,你使用 is 操作符来检测类型,后者使用 as? 操作符来进行向下转型。

你可以通过 is 检测一个实例是否为某些类的子类。如果这个实例是子类的类型,is 操作符会返回 true, 如果不是,会返回 false

1
2
3
4
5
if object is UIButton {
// object is of type UIButton
} else {
// object is not of type UIButton
}

你还可以试着使用 as? 操作符来向下转型到子类。as? 操作符返回一个 Optional 值,这个值可以使用 if-let 语句绑定到一个常量上面。

1
2
3
4
5
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
}

关于更多信息,可以查看 Swift 变成语言中类型转换这章。

检测并转换到某个协议上与检测和转换到某个类上的语法相同。这里是使用 as? 来检测协议兼容性的一个例子:

1
2
3
4
5
if let dataSource = object as? UITableViewDataSource {
// object conforms to UITableViewDataSource and is bound to dataSource
} else {
// object not conform to UITableViewDataSource
}

注意在这个转换后,dataSource 常量为 UITableViewDataSource 类型,这样你只能调用 UITableViewDataSource 中得方法和属性。如果你要进行其他操作,你必须把他转换成另外的类型。
关于更多的信息,可以查看 Swift 编程语言中协议一章
`

如果你觉得这篇文章有帮助,还可以关注微信公众号 swift-cafe,会有更多我的原创内容分享给你~

本站文章均为原创内容,如需转载请注明出处,谢谢。




微信公众平台
更多精彩内容,请关注微信公众号


公众号:swift-cafe
邮件订阅
请输入您的邮箱,我们会把最新的内容推送给您: