美文网首页
iOS NSNotification通知和KVO的使用

iOS NSNotification通知和KVO的使用

作者: 丶天空蓝丶 | 来源:发表于2020-07-08 10:49 被阅读0次
    一:KVO: 键值观察

    是基于键值编码实现的一种观察者机制,其实现依赖于 Objective-C 强大的 Runtime,当观察某对象 A 时,KVO 机制动态创建一个对象A当前类的子类,并为这个新的子类重写了被观察属性 keyPath 的 setter 方法。setter 方法随后负责通知观察对象属性的改变状况。
    Apple 使用了 isa-swizzling 来实现 KVO 。当观察对象A时,KVO机制动态创建一个新的名为:NSKVONotifying_A的新类,该类继承自对象A的本类,且 KVO 为 NSKVONotifying_A重写观察属性的setter 方法,setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象属性值的更改情况。

    KVO的使用:

    1、创建观察对象,在当前类中监测searchString这个字段值是否发生改变

    [self addObserver:self forKeyPath:@"searchString" options:NSKeyValueObservingOptionNew context:nil];
    

    2、获取监听,当searchString这个字段值发生改变后,会调用该方法.$\color{red}{r如果searchString为属性,不能使用 _searchString=@"新值" 这种方法改值,需要用 self.searchString=@"新值" 这种方法,否则不会调用下面的方法}

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    //    keyPath判断是否是当前监听的值
        if ([keyPath isEqualToString:@"searchString"]) {
    //        change[@"new"]获取改变后的值
            _searchStr = change[@"new"];
        }
    }
    

    3、移除观察,一般在dealloc方法里面执行

    -(void)dealloc {
        [self removeObserver:self forKeyPath:@"searchString"];
    }
    
    二:NSNotification通知

    是使用观察者模式来实现用于跨层传递消息的机制,传递方式是一对多的

    通知 的使用

    1、注册监听

    //监听searchStringChange字段,如果收到通知调用searchStringChangeNotification方法
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(searchStringChangeNotification:) name:@"searchStringChange" object:nil];
    
    -(void)searchStringChangeNotification:(NSNotification *)notification {
    //notification.object为searchStringChange 改变后的值
        _searchStr = notification.object;
    }
    
    

    2、发送通知

    //在searchStringChange字段值改变的地方发送通知,这是就会触发searchStringChangeNotification方法
    [[NSNotificationCenter defaultCenter] postNotificationName:@"searchStringChange" object:_searchStringChange];
    

    3、移除通知,一般在dealloc方法里面执行

    -(void)dealloc {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    三:使用注意事项

    1、如果用通知监听系统的属性,则不需要实现第二步发送通知,如监听键盘事件只需第一步和第三步

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowNew:) name:UIKeyboardWillShowNotification object:nil];
    

    2、关于移除。现在基本大家测试环境都是iOS13,发现 KVO和通知的第三步移除不写,也没有任何问题。这里说明下,通知的移除是在iOS9.0及以后可以不写了,如果你的项目支持iOS8.0,你也不写通知移除,那么在8.0版本上就会报错;KVO的移除忘了是在iOS11还是iOS12后才可以不写,否则也会报错。

    四:同异步

    1、通知和KVO都是同步的,即在调起监听后,执行完监听内容才会执行后续代码。

    2、KVO实现异步,创建一个异步线程,将值改变放在里面

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       self.searchString = @"值改变";
    });
    

    3、通知实现异步,创建一个异步线程,将发送通知放在里面,或者处理事件放在里面

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       [[NSNotificationCenter defaultCenter] postNotificationName:@"searchString" object:@"值改变"];
    });
    或
    -(void)searchStringChangeNotification:(NSNotification *)notification {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
           sleep(3);
           NSLog(@"%@",notification.object);
        });
    }
    

    4、另外,通知的异步可以用NSNotificationQueue,将通知放到通知异步缓冲队列中实现异步操作。将发送通知改成下面代码即可

    NSNotification *notification = [NSNotification notificationWithName:@"searchString" object:@"值改变"];
    [[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
    

    相关文章

      网友评论

          本文标题:iOS NSNotification通知和KVO的使用

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