美文网首页
聊聊 KVO

聊聊 KVO

作者: Hancle | 来源:发表于2017-11-07 15:02 被阅读0次

引用:http://khanlou.com/2013/12/kvo-considered-harmful/

细数KVO的弊端:

  1. 所有实现都在同一个方法里调用
 - (void)addObserver: (NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context 

比如说我需要观察tablview的contentsize属性,我这样来写:

 [_tableView addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];  

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {  
    [self configureView];  
}  

完成了?看起来很简单啊,so young,为了写这个,我们还需要做些额外的工作 orz

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {  
    if (object == _tableView && [keyPath isEqualToString:@"contentSize"]) {  
        [self configureView];  
    }  
} 
  1. KVO is string-ly typed
    keypath ‘contentSiz’ 是字符串类型的,这就意味着编译器跟解析器不会告诉你这个属性是什么类型的或者存不存在。它只是一个字符串。我们只能使用NSStringFromSelector(@selector(contentSize))来让编译器告诉我们这个存不存在。
    另外,当我们观察一个view controller时,想要获取它scrollview的contentsize,这时候keypathscrollview.contentOffset。这种情况下我们能做的事就更少了。
  2. KVO 必须处理父类实现
    我们也许还有一个父类也在监听,并实现了这个接口方法,那我们就该调用super方法
    if (object == _tableView && [keyPath isEqualToString:@"contentSize"]) {  
        [self configureView];  
    } else {  
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];  
    }  
} 

如果我们一不小心忘了,那就可能导致父类监听失效。
所以保险起见,我们最好不嫌麻烦地调用super方法 orz。

  1. KVO 在解除注册的时候可能导致crash
    我们一般会在-dealloc[_tableView removeObserver:self forKeyPath:NSStringFromSelector(@selector(contentSize)) context:NULL];
    但值得注意的是,tableview有可能会dealloc两次,这种情况下因为我们尝试remove同一个observance两次,就可能导致我们的app crash掉。另外,当父类也在监听同一属性的时候,也可能会调用两次导致crash。
    这个时候是该用到 context ,我们可能会context 当做 self来用,但在父类里,就不好用了。 (因为self不管在父类还是子类中都会指向同一个对象)所以推荐使用静态指针来存储context。
static void *ClassNameTableViewContentSizeContext = &ClassNameTableViewContentSizeContext;  
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {  
   if (context == ClassNameTableViewContentSizeContext) {  
       [self doThing];  
   } else if (context == OtherContext) {  
       [self doOtherThing];  
   } else {  
       [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];  
   }  
}  
  1. KVO太难调试
    delegate调试时,很容易就追踪到设置它的对象了,但KVO则可能需要在运行时使用 isKindOfClass:来追踪。
    这个就不用多举例子了,用过的人都有体会。

相关文章

  • 聊聊KVO

    iOS中的KVO用起来还是蛮爽的,特别适合用在Model更改后刷新UI等操作,可以很方便的监听一个对象属性值的变化...

  • 聊聊 KVO

    引用:http://khanlou.com/2013/12/kvo-considered-harmful/ 细数K...

  • iOS-KVO浅谈

    上一篇:iOS-KVC浅谈 前言:KVO 作为 KVC 的同袍兄弟,功能更强大,聊聊 KVO。 一、KVO 简介 ...

  • 聊聊 KVO 与 KVC 吧

    先聊聊 KVO 与 KVC 的区别吧:KVO是指键-值-观察者模式, 键值监听, 监听一个对象属性值的改变。KVO...

  • 聊聊 KVC KVO

    KVC NSKeyValueCoding 协议 键值编码(key-value),指定的key获取对应value...

  • iOS之解耦机制

    聊聊delegate, block, notification, KVO 一 高内聚低耦合是软件设计永恒的主题之一...

  • iOS原理篇(一): KVO实现原理

    KVO实现原理 什么是 KVO KVO 基本使用 KVO 的本质 总结 一 、 什么是KVO KVO(Key-Va...

  • 04. KVO使用,原理,本质

    问题 KVO日常使用 KVO原理(KVO本质是什么) 如何手动触发KVO 直接修改成员变量会触发KVO吗 KVO图...

  • 20.iOS底层学习之KVO 原理

    本篇提纲1、KVO简介;2、KVO的使用;3、KVO的一些细节;4、KVO的底层原理; KVO简介 KVO全称Ke...

  • 深入理解KVO

    iOS | KVO | Objective-C KVO的本质是什么,如何手动触发KVO? 1.什么是KVO KVO...

网友评论

      本文标题:聊聊 KVO

      本文链接:https://www.haomeiwen.com/subject/ngodmxtx.html