zoukankan      html  css  js  c++  java
  • KVO等具体实现步骤以及注意事项

    KVO是一种设计模式,名为观察者.

    addObserver:forKeyPath:options:context:

    通知其他对象的方法,这个方法在NSObject中就已经申明了,也就是说任何继承自NSObject的对象都可以使用KVO.

    我们来实现一个对象a值改变的时候去通知对象b.

    新建两个ModelA ModelB 类.

    ModelA.h + ModelA.m

    复制代码
    #import <Foundation/Foundation.h>
    
    @interface ModelA : NSObject
    
    @property (nonatomic, strong) NSString *name;
    
    @end
    复制代码
    #import "ModelA.h"
    
    @implementation ModelA
    
    @end

    ModelB.h + ModelB.m

    复制代码
    #import <Foundation/Foundation.h>
    
    @interface ModelB : NSObject
    
    @property (nonatomic, strong) NSString *sex;
    
    @end
    复制代码
    复制代码
    #import "ModelB.h"
    
    @implementation ModelB
    
    -(void)observeValueForKeyPath:(NSString *)keyPath
                         ofObject:(id)object
                           change:(NSDictionary *)change
                          context:(void *)context
    {
        self.sex = @"female";
    }
    
    @end
    复制代码

    请将如下延时执行的代码添加进工程当中

    - (void)delay:(int64_t)delta execute:(dispatch_block_t)block
    {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delta * NSEC_PER_SEC),
                       dispatch_get_main_queue(), block);
    }

    然后再写如下的代码:

    执行结果如下:

    2014-05-06 17:40:35.346 FileManager[20208:60b] Application windows are expected to have a root view controller at the end of application launch
    2014-05-06 17:40:37.347 FileManager[20208:60b] female

    如果注释掉ModelB中的方法observeValueForKeyPath:ofObject:change:context:,运行时会导致崩溃:

    如果重复移除了两次,也会导致崩溃-_-!!!!

    也就是这么一层关系:

    A对象要通知B对象,B对象必须实现监听的方法,否则一旦有消息发送就会导致崩溃.

    A对象不想通知B对象了,需要从B对象身上移除掉通知.

    要想程序不出现问题,我们需要实现3步.

    (主动添加B的通知) A -------> B(不实现一个方法就崩溃)

    (主动移除B的通知) A ---X-->  B

    (重复移除B的通知) A ---X-->  B(崩溃)

    用起来很恶性,还好,我们可以重复添加B的通知而不崩溃......

    问题:在ARC中我们需要移除KVO的observer么?

    You should explicitly remove the observer even you use ARC. Create a dealloc method and remove there..

    -(void)dealloc {[[NSNotificationCenter defaultCenter] removeObserver:self];}

    If you see the method you don't need to call [super dealloc]; here, only the method without super dealloc needed.

    你需要非常明确的移除你的通知者,即使是在ARC中.创建一个dealloc方法然后在方法里面移除.

    ARC中你不需要调用[super dealloc].

    问题:ARC给一个对象添加了observer有可能会导致循环应用什么的么?

    You need to call removeObserver, ARC only automates retain counts. removeObserver does not impact the retain count.

    你需要调用removeObserver,ARC只是自动管理了retain counts,removeObserver并不影响retain count.(这一点我不确定,有待验证)

    问题:当要通知的对象已经nil了,这个通知会自动移除吗?

    Observers are not removed automatically. From the NSNotificationCenter Class Reference:

    观察者不会自动移除,请查看NSNotificationCenter类的原文引述:

    Important: The notification center does not retain its observers, therefore, you must ensure that you unregister observers (using removeObserver: or removeObserver:name:object:) before they are deallocated. (If you don't, you will generate a runtime error if the center sends a message to a freed object.)

    很重要:通知中心并不会retain他的观察者,所以,你必须确保你那些对象销毁之前注销掉观察者,否则就会出现错误.

    You should therefore call

    [[NSNotificationCenter defaultCenter] removeObserver:self];

    in your dealloc method if you are not 100% sure that the observer was not removed previously.

    https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html#//apple_ref/occ/instm/NSObject/addObserver%3aforKeyPath%3aoptions%3acontext%3a

    addObserver:forKeyPath:options:context:

    Registers anObserver to receive KVO notifications for the specified key-path relative to the receiver.

    - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
    Parameters
    anObserver

    The object to register for KVO notifications. The observer must implement the key-value observing method observeValueForKeyPath:ofObject:change:context:.

    keyPath

    The key path, relative to the receiver, of the property to observe. This value must not be nil.

    options

    A combination of the NSKeyValueObservingOptions values that specifies what is included in observation notifications. For possible values, see “NSKeyValueObservingOptions.”

    context

    Arbitrary data that is passed to anObserver in observeValueForKeyPath:ofObject:change:context:.

    Discussion
  • 相关阅读:
    Spring Boot
    Spring Boot Tomcat配置详解
    Spring Boot读取配置的 5 种方式
    Spring Boot日志集成实战
    Spring Boot国际化开发实战
    Spring Boot整合 Thymeleaf 模板引擎
    Spring Boot Debug调试
    Spring Boot实现热部署
    Exchange Cards(dfs)
    Dungeon Master
  • 原文地址:https://www.cnblogs.com/xujiahui/p/6412951.html
Copyright © 2011-2022 走看看