Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 用于整个对象属性的KVO_Objective C_Ios_Key Value Observing - Fatal编程技术网

Objective c 用于整个对象属性的KVO

Objective c 用于整个对象属性的KVO,objective-c,ios,key-value-observing,Objective C,Ios,Key Value Observing,是否可以添加观察者,以便在任何受监视对象属性被修改时获得通知?例如: @interface OtherObject : NSObject @property (nonatomic) MyObject* myObject; @end 及 我想做一些类似的事情: [otherObject addObserver:self forKeyPath:@"myObject" options:0 con

是否可以添加观察者,以便在任何受监视对象属性被修改时获得通知?例如:

@interface OtherObject : NSObject

@property (nonatomic) MyObject* myObject;

@end

我想做一些类似的事情:

[otherObject addObserver:self
               forKeyPath:@"myObject"
                  options:0
                  context:nil]

如果修改了property1或property2,则会收到通知。如果我注册保持对象,它似乎不起作用(例如,在我修改属性1时,myObject并没有被真正修改,这在某种程度上是有意义的)。

您可以使用一个函数来修改myObject的特定属性

-(void)setMyObjectName:(NSString*)name;
然后在函数中有这个代码

- (void)setMyObjectName:(NSString*)name
{
    [self willChangeValueForKey:@"myObject"];

    myObject.name = name;

    [self didChangeValueForKey:@"myObject"];
}
当myObject上的属性发生更改时,这将通知观察者

无论何时需要,请使用此模式,您都可以收到myObject上任何更改的通知

::编辑:: 话虽如此,你应该能够使用

[otherObject addObserver:self
              forKeyPath:@"myObject.property1"
                 options:0
                 context:nil];
这将观察属性1,并对其他属性进行同样的处理

@interface MyObject : NSObject
@property (nonatomic) id masterProperty;
@property (nonatomic) unsigned int property1;
@property (nonatomic) unsigned int property2;
@end

但这将意味着为每个属性分别添加一个观察者。

我可以想到两个选项

  • 您可以创建一个单独的“主”属性,并使其依赖于所有其他属性

    @interface MyObject : NSObject
    @property (nonatomic) id masterProperty;
    @property (nonatomic) unsigned int property1;
    @property (nonatomic) unsigned int property2;
    @end
    

    如果您观察到
    masterProperty
    ,当任何属性发生更改时,都会收到通知

  • 您可以使用Objective-C运行时获取所有属性的列表,并对其进行观察

    - (void)addObserverForAllProperties:(NSObject *)observer
                                options:(NSKeyValueObservingOptions)options
                                context:(void *)context {
        unsigned int count;
        objc_property_t *properties = class_copyPropertyList([self class], &count);
        for (size_t i = 0; i < count; ++i) {
            NSString *key = [NSString stringWithCString:property_getName(properties[i])];
            [self addObserver:observer forKeyPath:key 
                      options:options context:context];
        }
        free(properties);
    }
    
    -(void)addObserverForAllProperties:(NSObject*)observer
    选项:(NSKeyValueObservingOptions)选项
    上下文:(void*)上下文{
    无符号整数计数;
    objc_property_t*properties=class_copyPropertyList([self class],&count);
    用于(大小i=0;i

    • 鼓手回答的Swift版本,带有一个附加功能来删除观察结果(例如在
      deinit
      ):

      扩展对象{ func addObserverForAllProperties( 观察员:NSObject, 选项:NSKeyValueObservingOptions=[], 上下文:UnsafeMutableRawPointer?=nil ) { PerformForallKeyPath{keyPath in addObserver(观察者,forKeyPath:keyPath,选项:选项,上下文:上下文) } } func removeObserverForAllProperties( 观察员:NSObject, 上下文:UnsafeMutableRawPointer?=nil ) { PerformForallKeyPath{keyPath in removeObserver(观察者,forKeyPath:keyPath,context:context) } } func PerformForAllKeyPath(u操作:(字符串)->Void){ 变量计数:UInt32=0 guard let properties=class\u copyPropertyList(object\u getClass(self),&count)else{return} 延迟{free(properties)} 对于0中的i..
      也许willChangeValueForKey而不是willChangeObjectForKey?@Andy改变了。令人惊讶的是,这两年都没有被发现。英雄联盟您可能还可以将这两种方法结合起来,使用Objective-C运行时获取KeyPathsForvaluesFectingMasterProperty中所有属性的列表,然后在NSSet中返回它们。(使用静态变量可能是一个好主意,这样您只需执行一次即可。)下面添加了Swift版本:
      - (void)addObserverForAllProperties:(NSObject *)observer
                                  options:(NSKeyValueObservingOptions)options
                                  context:(void *)context {
          unsigned int count;
          objc_property_t *properties = class_copyPropertyList([self class], &count);
          for (size_t i = 0; i < count; ++i) {
              NSString *key = [NSString stringWithCString:property_getName(properties[i])];
              [self addObserver:observer forKeyPath:key 
                        options:options context:context];
          }
          free(properties);
      }