NSObject中属性更改的通知

时间:2013-11-26 19:14:11

标签: ios properties nsnotificationcenter key-value-coding

是否可以通知对象中所有属性的更改?我想在NSObject中的某个属性发生更改时调用selector

到目前为止,我只看过keyPathsForValuesAffectingValueForKey:,这不是我想要的,但它一直存在于我的搜索结果中。

我目前的具体目标是拥有一个" FilterModel"具有特定过滤器特性的属性。更改任何属性后,我想使用新过滤的结果更新UITableView

3 个答案:

答案 0 :(得分:4)

根据您的需要,这两个选项中的一个可能是您正在寻找的。

KVO观察

KVO Observing提供了一个框架,用于自动监听属性更改,而无需修改getter和setter。只需通过以下方式将您的侦听对象添加为观察者或目标对象:

addObserver:forKeyPath:options:context:

然后在观察者的实现中,实现:

observeValueForKeyPath:ofObject:change:context:

并检查捕获通知的路径是否与所需属性匹配。有关接收KVO通知的详情,请参阅this。有关KVO观察概念的更多详细信息和更好的可视化,请参阅KVO Developer documentation

手动NSNotifications

如果您想微调您感兴趣的更改,每当您通过设置者更改您感兴趣的对象时,都会通过以下方式发布通知:

postNotificationName:object:userInfo:

这将允许您精确定制您感兴趣的更改,而不是希望从keyPathsForValuesAffectingValueForKey:之类的内容中寻找您所需的确切行为。然后,您可以通过以下方式在相关视图中收听您的命名通知来捕获这些通知:

addObserver:selector:name:object:

您可以阅读有关在NSNotificationCenter documentation上发布通知的详情。

答案 1 :(得分:3)

您可以通过使用Objective-C运行时查询对象的属性列表并将自定义类作为观察者注册到它们来实现。

id yourObject;

objc_property_t* properties = class_copyPropertyList([yourObject class], &count);
NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++)
{
    const char* propertyName = property_getName(properties[i]);
    NSString *stringPropertyName = [NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
    [yourObject addObserver:self forKeyPath:stringPropertyName options:NSKeyValueObservingOptionNew context:nil];
}

另外,在释放之前,不要忘记从观察者列表中删除自定义类。每当属性发生变化时,被调用的方法是:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

答案 2 :(得分:2)

- (id)init
{
    if(self = [super init])
    {
        unsigned int propertyCount;
        objc_property_t *properties = class_copyPropertyList([self class], &propertyCount);
        for(int i = 0; i < propertyCount; i++)[self addObserver:self forKeyPath:[NSString stringWithCString:property_getName(properties[i]) encoding:NSUTF8StringEncoding] options:NSKeyValueObservingOptionNew context:nil];
    }
    return self;
}

- (void)dealloc
{
    unsigned int propertyCount;
    objc_property_t *properties = class_copyPropertyList([self class], &propertyCount);
    for(int i = 0; i < propertyCount; i++)[self removeObserver:self forKeyPath:[NSString stringWithCString:property_getName(properties[i]) encoding:NSUTF8StringEncoding]];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"Changed value at key path: %@", keyPath);
}