键值观察-如何观察对象的所有属性?

问题描述 投票:16回答:2

我对键值观察(KVO)的使用以及如何注册以接收属性更改通知感到满意:

[account addObserver:inspector
          forKeyPath:@"openingBalance"
             options:NSKeyValueObservingOptionNew
              context:NULL];

但是,如果我想观察帐户对象所有属性的变化,如何实现?我是否需要注册每个属性的通知?

objective-c key-value-observing
2个回答
19
投票
似乎没有内置的功能可以订阅对象所有属性的更改。

如果您不关心确切的属性已更改,并且可以更改您的类,则可以向其添加虚拟属性以观察其他属性的更改(使用+ keyPathsForValuesAffectingValueForKey+keyPathsForValuesAffecting<Key>方法:]

// .h. We don't care about the value of this property, it will be used only for KVO forwarding @property (nonatomic) int dummy; #import <objc/runtime.h> //.m + (NSSet*) keyPathsForValuesAffectingDummy{ NSMutableSet *result = [NSMutableSet set]; unsigned int count; objc_property_t *props = class_copyPropertyList([self class], &count); for (int i = 0; i < count; ++i){ const char *propName = property_getName(props[i]); // Make sure "dummy" property does not affect itself if (strcmp(propName, "dummy")) [result addObject:[NSString stringWithUTF8String:propName]]; } free(props); return result; }

现在,如果您观察dummy属性,则每次更改对象的任何属性都会收到KVO通知。

此外,您还可以像发布的代码中那样获取对象中所有属性的列表,并在循环中为每个属性订阅KVO通知(这样就不必对属性值进行硬编码)-这样,您将获得如果需要,可以更改属性名称。


0
投票
以下Swift代码为每个属性添加了观测值,如David van Brink所建议。它具有删除观察结果的附加功能(例如,在deinit中):

extension NSObject { func addObserverForAllProperties( observer: NSObject, options: NSKeyValueObservingOptions = [], context: UnsafeMutableRawPointer? = nil ) { performForAllKeyPaths { keyPath in addObserver(observer, forKeyPath: keyPath, options: options, context: context) } } func removeObserverForAllProperties( observer: NSObject, context: UnsafeMutableRawPointer? = nil ) { performForAllKeyPaths { keyPath in removeObserver(observer, forKeyPath: keyPath, context: context) } } func performForAllKeyPaths(_ action: (String) -> Void) { var count: UInt32 = 0 guard let properties = class_copyPropertyList(object_getClass(self), &count) else { return } defer { free(properties) } for i in 0 ..< Int(count) { let keyPath = String(cString: property_getName(properties[i])) action(keyPath) } } }

© www.soinside.com 2019 - 2024. All rights reserved.