Swift 4 新知:KVC和KVO新姿势

.

1、struct 也支持 KVC

一个感人的进步就是 struct 也支持 KVC 了。但是并不是使用原有的setValue:forKeypath的api。而是利用了swfit 4增加的一个语法特性:自定义索引可以有参数名。

直接上代码吧:

struct ValueType {
    var name:String
}
 
var object = ValueType(name: "zhuo")
let name = \ValueType.name
 
// set
object[keyPath: name] = "swift4"
// get
let valueOfName = object[keyPath:name]

//这种写法和上面的等同
object[keyPath : \Value.name] = "swift4"
let valueName = object[keyPath: \Value.name]

2、KVO

遗憾的是依然只有 NSObject 才能支持 KVO。Swift 4中的一个对此有影响的改变是继承 NSObject 的 swift class 不再默认全部 bridge 到 OC。原因可以参考我的前一篇博客:《Swift 4新知:自动清除冗余代码减小包大小》。然而 KVO 又是一个纯 OC 的特性,所以如果是 swift class 需要在声明的时候增加 @objcMembers 关键字。否则在运行的时候你会得到一个 error:

fatal error: Could not extract a String from KeyPath Swift.ReferenceWritableKeyPath<iOS11.XXX, Swift.String>

另外一件事就是被观察的属性需要用dynamic修饰,否则也无法观察到。

一个好消息是不需要在对象被回收时手动 remove observer。但是这也带来了另外一个容易被忽略的事情:观察的闭包没有被强引用,需要我们自己添加引用,否则当前函数离开后这个观察闭包就会被回收了。

@objcMembers class OCClass: NSObject {
    dynamic var name: String
 
    init(name: String) {
        self.name = name
    }
}
 
class ViewController: UIViewController {
 
    var swiftClass: OCClass!
    var ob: NSKeyValueObservation!
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
        swiftClass = OCClass(name: "oc")
        ob = swiftClass.observe(\.name) { (ob, changed) in
            let new = ob.name
            print(new)
        }
        swiftClass.name = "swift4"
    }
}

KVO 之后返回的是一个 NSKeyValueObservation 实例,需要自己控制这个实例的生命周期。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,222评论 30 472
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,827评论 0 9
  • 前言 谁能不爱 KVO 呢,一处修改,处处得知,多么优雅的模式啊!等等 Notification 模式也可以啊,咳...
    seedante阅读 20,366评论 13 28
  • Swift 介绍 简介 Swift 语言由苹果公司在 2014 年推出,用来撰写 OS X 和 iOS 应用程序 ...
    大L君阅读 3,315评论 3 25
  • 你在写销售文案的时候,有没考虑过类似这样的问题,比如怎样写才能改变受众的态度或者决定,也就是说你怎样做才能说服受众...
    元兵阅读 717评论 0 0