温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

详解在Swift中使用KVO

发布时间:2020-07-21 11:42:02 来源:亿速云 阅读:395 作者:小猪 栏目:开发技术

小编这次要给大家分享的是详解在Swift中使用KVO,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。

在文字的开头,先说一个小细节,swift中声明一个类,你可以集成自NSObject,也可以选择忽略,二者有什么区别呢。根据自己的经验,我得出以下结论。不足之处,请指出。exmple:我们声明这样一个类

class Person: NSObject {
  var name: String?
  override init() {
    super.init()
  }
}
此类打印出的内存地址是0x00000fbd00007ffeefbfc240

这段代码是不会报错的,是一个典型的swift遗留ObjC语法的写法,但是如果我们去掉NSObject并打印出他的内存地址,如下

class Person {
  var name: String?
  init() {
    
  }
}
此类打印出的内存地址是0x00007ffeefbfc240
  • 内存地址不一样,继承自NSObject的类对象的内存地址明显长度多了8个长度,why?多出的8个空间就是为了存放ObjC对象内的isa指针,有兴趣的可以往下研究。
  • 继承自NSObject的类可以使用OC里的一些骚操作,比如KVC、KVO、runtime,否则使用setValue-forKey时是会报错的。

区别还有很多,平时在开发中大家可以多注意这一区别。个人偏向不继承NSObject,尤其是我需要此类做一些骚操作时,比如KVO。

KVO是OC一个对象属性的特性,由于是面向字符串,所以开发时需要尤其小心,这种奔溃只有执行到了才会报错。声明如下类:

class Person: NSObject {
   @objc var age: Int?
   var name: String?
   var observation: NSKeyValueObservation?
   
   override init() {
    super.init()
    self.observation = observe(\Person.age, options: .new, changeHandler: { (person, change) in
      print("Person.age的新值 = ", change.newValue as Any)
    })
  }
}

在外部我们,初始化一个对象,并对age进行赋值,如下

let person = Person()
person.age = 18
person.setValue(100, forKey: "age")

程序执行后,(ÒωÓױ)!为什么只有一个打印?按理说是应该打印Person.age的新值 = 18Person.age的新值 = 100的呀,然而并没有:laughing:。问题出在哪,原来,swift中如果需要对一个值进行监听,那么一定要记住2个关键词

  • @objc
  • dynamic

否则,

没有@objc程序在监听时会触发奔溃;没有dynamic则属性的set方法不会生效,自然就没有上面的打印,因为KVO的本质就是监听属性的set方法,而可变数组的增删操作都不会生效;

但是为什么KVC的操作却能生效呢?这是因为KVC内部的实现过程是

  • [person willChangeValueForKey:@"age"];
  • person->_age = 10;
  • [person didChangeValueForKey:@"age"];
  • 而didChangeValueForKey:内部会调用observe的observeValueForKeyPath:ofObject:change:context:的方法,也就触发了KVO

所以正确的写法应该是

class Person: NSObject {
   @objc dynamic var age: Int?
   var name: String?
   var observation: NSKeyValueObservation?
   
   override init() {
    super.init()
    self.observation = observe(\Person.age, options: .new, changeHandler: { (person, change) in
      print("Person.age的新值 = ", change.newValue as Any)
    })
  }
}

看完这篇关于详解在Swift中使用KVO的文章,如果觉得文章内容写得不错的话,可以把它分享出去给更多人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI