【iOS开发】KVO传值

39 篇文章 0 订阅

注册观察者:

(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
  1. observer:观察者,监听属性变化的对象。 该对象必须实现observeValueForKeyPath:ofObject:change:context: 方法。
  2. keyPath:要观察的属性名称。要和属性声明的名称一致。
  3. options:对KVO机制进行配置,修改KVO通知的时机以及通知的内容
  4. context: 传入任意类型的对象,在"接收消息回调"的代码中可以接收到这个对象,是KVO中的一种传值方式。

四个options:

enum {
    // 提供属性的新值
    NSKeyValueObservingOptionNew = 0x01,
 
    // 提供属性的旧值
    NSKeyValueObservingOptionOld = 0x02,
 
    // 如果指定,则在添加观察者的时候立即发送一个通知给观察者,
    // 并且是在注册观察者方法返回之前
    NSKeyValueObservingOptionInitial = 0x04,
 
    // 如果指定,则在每次修改属性时,会在修改通知被发送之前预先发送一条通知给观察者,
    // 这与-willChangeValueForKey:被触发的时间是相对应的。
    // 这样,在每次修改属性时,实际上是会发送两条通知。
    NSKeyValueObservingOptionPrior = 0x08 
};
typedef NSUInteger NSKeyValueObservingOptions;

接受通知:

- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context;

取消注册:

- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

举例:
有两个视图控制器,点按第一个视图的skip按钮跳转到第二个界面,第二个界面有一个一个keyTextField和keyString属性,更改keyTextField的text,再把text赋给keyString。返回第一个页面,labelChanging的文字改变。
实现:
在第一个视图控制器中的skip按钮事件里:

- (void)pressSkipButton {
    _secondPage = [[SecondViewController alloc] init];
    [_secondPage addObserver:self forKeyPath:@"keyString" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
    [self.navigationController pushViewController:_secondPage animated:YES];
}

再添加接收通知方法:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    NSLog(@"%@",keyPath);
    if ([keyPath isEqualToString:@"keyString"] && object == _secondPage) {
        _labelChanging.text = [change valueForKey:@"new"];
        //change的使用:上文注册时,枚举为2个,因此可以提取change字典中的新、旧值的这两个方法
        NSLog( @"old:%@ new:%@",[change valueForKey: @"old"], [change valueForKey: @"new"]);
    }
}

最后:

- (void)dealloc {
    [_secondPage removeObserver:self forKeyPath:@"keyString"];
}

在第二个视图控制器中(菜鸡偷懒就写在viewWillDisappear里了):

- (void)viewWillDisappear:(BOOL)animated {
    self.keyString = _keyTextField.text;
}

这样就可以实现功能(效果图):
请添加图片描述
请添加图片描述
输出结果:
请添加图片描述
若是直接

_keyString = _keyTextField.text;

不会成功,因为没有调用setter方法。
注意,在观察数组的变化时,在第二个视图控制器中如直接使用:

[_array addObject:@"1"];

是不会触发KVO的。可以使用以下形式:

[_array addObject:@"1"];
self.array = self.array;

这样使用点语法会调用setter方法,调用setter方法会触发KVO,或者使用:

[self willChangeValueForKey:@"array"];
[_array addObject:@"1"];
[self didChangeValueForKey:@"array"];

手动触发KVO。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值