【问题标题】:KVO With NSMutableArrayKVO 与 NSMutableArray
【发布时间】:2011-08-07 23:41:41
【问题描述】:

我的 AppDelegate 中有一个 NSMutableArray 属性,称为块。 我想观察何时将对象添加到此数组中。 我读过其他帖子,但我不明白为什么这不起作用。

在我的应用委托类中,我实现了

- (void)insertObject:(id)obj inBlocksAtIndex:(NSInteger)index
{
    [blocks insertObject:obj atIndex:index];
}

在我的视图控制器的 init 方法中,我向我的 AppDelegate 引用添加了一个观察者。

boardModel = [[UIApplication sharedApplication] delegate];
[boardModel addObserver:self forKeyPath:@"blocks" options:0 context:NULL];

在我的视图控制器的 viewDidLoad 方法中,我尝试调用我之前实现的 KVO 索引数组访问器,

[boardModel insertObject:[[Block alloc] init] inBlocksAtIndex:0];

然后我实现了我的 observeValueForKeyPath 方法:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"blocks"])
    {
        NSLog(@"ADDED");
    }
}

我试过在observeValueForKeyPath的if语句之前添加一个NSLog语句,看起来好像从来没有被调用过。

我也试过 NSLogging [[boardModel blocks] count],它说计数是 1(正在添加对象)。

我一定是错过了什么。

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    问题是NSArrays 不尊重 KVO,因此观察关键路径计数是行不通的。

    如果这是 MacOSX,请使用 NSArrayController。否则为数组实现一个包装类,在添加/删除数组内容时触发 KVO 调用,并传递所有其他调用。

    【讨论】:

      【解决方案2】:

      您正在观察应用委托的 blocks 属性,而不是 blocks 数组本身。希望下面的例子能清楚地说明区别:

      // This will fire KVO as you're changing the app delegate's `blocks` property.
      appDelegate.blocks = [NSMutableArray array];
      
      // This will not fire KVO as the app delegate's `blocks` property still points
      // to the same object; from the app delegate's perspective, nothing's happened.
      [appDelegate.blocks addObject:@"Object"];
      

      如果您想在blocks 数组的内容发生更改时收到通知,请观察数组本身的属性——类似于count。更新您的代码:

      [boardModel.blocks addObserver:self forKeyPath:@"count" options:0 context:NULL];
      

      【讨论】:

      • NSMutableArray 没有实现NSKeyValueCoding
      • 如果您正确访问数组,这将起作用:something = [self mutableArrayValueForKey:@"blocks"]; [某事 addObject:foo];
      【解决方案3】:

      你试过了吗

         - (void)insertObject:(id)obj inBlocksAtIndex:(NSInteger)index
          {
              [[self mutableArrayValueForKey:@"blocks"] insertObject:obj atIndex:index];
           }
      

      【讨论】:

        【解决方案4】:

        我刚刚开源了一个非常小的 Objective-C 库,它为 NSMutableArray 添加了一个委托。它可能会帮助您实现您想要做的事情。查看FCMutableArray on GitHub

        【讨论】:

          【解决方案5】:

          并不是说 NSMutableArray 在某些方面不符合 KVO,而是所有符合 KVO 的属性都必须是 NSObjects。 "count" 是一个 NSUInteger;您无法直接观察该属性。如果它是一个 NSNumber 对象,你可以。

          来自 NSArray 头文件:

          @interface NSArray<__covariant ObjectType> : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
          
          @property (readonly) NSUInteger count;
          

          顺便说一句,为什么答案被接受了?很明显,回答者没有测试他的答案。

          【讨论】:

            猜你喜欢
            • 2023-03-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-08-17
            • 2012-01-23
            • 2011-04-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多