KVO---注册依赖的Keys

有很多情况,一个属性的值是依赖于其它一个或多个其它对象的属性.如果一个属性的值更改,那么派生属性的值也应该被标记为更改.

对单关系(To-One)

你要重写keyPathsForValuesAffectingValueForKey:方法

比如:
fullName依赖于firstName和lastName:

- (NSString *)fullName {
    return [NSString stringWithFormat:@"%@ %@",firstName, lastName];
}

当firstName或lastName被改变时,都要通知到那些观察fullName属性的对象.
一种解决办法是重写keyPathsForValuesAffectingValueForKey:指明fullName属性是依赖于lastNamefirstName属性的.

+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
 
    NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
 
    if ([key isEqualToString:@"fullName"]) {
        NSArray *affectingKeys = @[@"lastName", @"firstName"];
        keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys];
    }
    return keyPaths;
}
class override func keyPathsForValuesAffectingValue(forKey key:String) -> Set<String>{
     <#Code#>
}

你也可以实现以下的方法来达到相同的目地,用以下的命名格式实现一个类方法keyPathsForValuesAffecting<Key>,<Key>是属性的名字(第一个字母要大写).比如:

+ (NSSet *)keyPathsForValuesAffectingFullName {
    return [NSSet setWithObjects:@"lastName", @"firstName", nil];
}

当你在category里增加了一个计算属性时,你不能重写keyPathsForValuesAffectingValueForKey:方法,因为你不能在category里重写方法.在这种情况下,你可以用keyPathsForValuesAffecting<Key>的类方法来实现这个机制(在swift里extension是不是也是这样的情况,有待验证).


对多关系(To-Many)

keyPathsForValuesAffectingValueForKey:不支持对多关系(Array等).有两种解决办法:
1.你把父注册为所有子的观察者,有一个子类变化了,你就会得到通知:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
 
    if (context == totalSalaryContext) {
        [self updateTotalSalary];
    }
    else
    // deal with other observations and/or invoke super...
}
 
- (void)updateTotalSalary {
    [self setTotalSalary:[self valueForKeyPath:@"employees.@sum.salary"]];
}
 
- (void)setTotalSalary:(NSNumber *)newTotalSalary {
 
    if (totalSalary != newTotalSalary) {
        [self willChangeValueForKey:@"totalSalary"];
        _totalSalary = newTotalSalary;
        [self didChangeValueForKey:@"totalSalary"];
    }
}
 
- (NSNumber *)totalSalary {
    return _totalSalary;
}

2.如果您使用的是Core Data,则可以将父注册到通知中心作为一个观察者。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 本文结构如下: Why? (为什么要用KVO) What? (KVO是什么) How? ( KVO怎么用) Mo...
    等开会阅读 5,582评论 1 21
  • 转载:http://yulingtianxia.com/blog/2014/05/12/objective-czh...
    F麦子阅读 4,585评论 0 0
  • 本文讲述了使用Cocoa框架中的KVC和KVO,实现观察者模式 键/值编码中的基本调用包括-valueForKey...
    茗涙阅读 3,998评论 0 3
  • 本篇会对KVO的实现进行探究,不涉及太多KVO的使用方法,但是会有一些使用时的思考。 一、使用上的疑问 1.key...
    奋拓达阅读 3,496评论 0 2
  • 或者KVO,是一个非正式协议,它定义了对象之间观察和通知状态改变的通用机制。 基本使用 使用KVO必须要满足的条件...
    一枚iOS程序猿阅读 4,110评论 0 0

友情链接更多精彩内容