Objective-C语言--Key-Value Observing Programming Guide

Registering for Key-Value Observing

1、注册对一个对象属性变化的监听

- (void)registerAsObserver {
  /*
  account被监听的对象
  inspector监听者
  openingBalance被监听对象中被监听的属性
  options监听选项
  */
  [account addObserver:inspector                       forKeyPath:@"openingBalance" 
  options:(NSKeyValueObservingOptionNew |
             NSKeyValueObservingOptionOld)
             context:NULL];
}

2、实现observeValueForKeyPath:ofObject:change:context:方法,当监听的属性发生变化时的逻辑处理。

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    if ([keyPath isEqual:@"openingBalance"]) {
        [openingBalanceInspectorField setObjectValue:
            [change objectForKey:NSKeyValueChangeNewKey]];
}
 /*
     Be sure to call the superclass's implementation *if it implements it*.
     NSObject does not implement the method.
     */
    [super observeValueForKeyPath:keyPath
                         ofObject:object
                           change:change
}

3、监听结束时,移除监听

- (void)unregisterForChangeNotification {
    [observedObject removeObserver:inspector forKeyPath:@"openingBalance"];
}

注意:1、监听不使用时,千万记得移除。2、如果子类和父类对同一个属性进行监听的时候,在父类中不需要注册监听,而是在子类中注册监听,但是在实现observeValueForKeyPath:ofObject:change:context:方法是,通过super关键字调用父类的实现,由于NSObject并没有实现observeValueForKeyPath:ofObject:change:context:这个方法,所以父类没有监听需求时,不需要通过super去调用父类这个方法。

KVO Compliance

自动发送通知

  1. [account setName:@”Savings”];
  2. [account setValue:@”Savings” forKey:@”name”];
  3. [document setValue:@”Savings” forKeyPath:@”account.name”];
    通过上述方式修改对象时都会自动触发通知。

手动发送通知

1、如果在自己的代码中不需要自动的发送通知。需要重写如下类方法。返回YES为自动发送,返回NO为手动发送。

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
    BOOL automatic = NO;
    if ([theKey isEqualToString:@"openingBalance"]) {
        automatic = NO;
    }
    else {
        automatic = [super automaticallyNotifiesObserversForKey:theKey];
}
    return automatic;
}

2、当上面方法返回NO的时候,需要我们手动的触发通知。即在需要发送通知的地方,添加willChangeValueForKey:和didChangeValueForKey:调用,例如:

- (void)setOpeningBalance:(double)theBalance {
    [self willChangeValueForKey:@"openingBalance"];
    _openingBalance = theBalance;
    [self didChangeValueForKey:@"openingBalance"];
}

3、为防止多余的触发还可以做进一步的优化

- (void)setOpeningBalance:(double)theBalance {
    if (theBalance != _openingBalance) {
        [self willChangeValueForKey:@"openingBalance"];
        _openingBalance = theBalance;
        [self didChangeValueForKey:@"openingBalance"];
} }

你可能感兴趣的:(Objective-C语言,ObjectiveC,iOS)