【问题标题】:KVO notifications on NSArray arrayByAddingObjectsFromArrayNSArray arrayByAddingObjectsFromArray 上的 KVO 通知
【发布时间】:2014-10-13 02:01:59
【问题描述】:

我正在通过块调用构建一个数组,并希望使用它来填充 UITableView 的单元格。我正在尝试使用 KVO 来监听对数组的更改,但我找不到针对它的方法。

这有点过时了,但它说 arrayByAddingObjectsFromArray 是我想要使用的。 https://github.com/sebastienwindal/iOSPatterns/wiki/Key-Value-Observing

添加观察者:

[self.array addObserver:self forKeyPath:@"arrayData" options:NSKeyValueObservingOptionNew context:nil];

然后将数据添加到数组中:

[array.arrayData arrayByAddingObjectsFromArray:newItems];

observeValueForKeyPath: 方法现在非常简单,只是提供了一个设置调试器断点的好地方。

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSLog(@"break here");
}

有什么想法吗?我应该改用 NSMutableArray 吗?

如果我的 SO 搜索不好并且已经被问了 200 次,请提前道歉。 ;)

【问题讨论】:

    标签: ios objective-c macos uitableview key-value-observing


    【解决方案1】:

    [array.arrayData arrayByAddingObjectsFromArray:newItems]; 所做的是通过复制 arrayData 中的所有元素来创建一个新数组 tempArray,然后将 newItems 附加到其末尾。

    我认为您想要的是获取新数组并将其分配回self.array by self.array = [self.array arrayByAddingObjectsFromArray:newItems];。在这种情况下,您的新 self.array 指向的新内存地址与您分配的内存地址不同。

    [self addObserver:self forKeyPath:@"array" options:NSKeyValueObservingOptionNew context:nil]; 前提是您有 NSArray *array 属性。

    与:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { NSLog(@"break here"); }

    您将能够监视其指针的变化。

    【讨论】:

      【解决方案2】:

      这个:

      [array.arrayData arrayByAddingObjectsFromArray:newItems];
      

      实际上没有效果。 -arrayByAddingObjectsFromArray: 创建并返回一个新数组。它不会影响接收器 (array.arrayData)。由于您没有对返回的值做任何事情,所以它只是被丢弃了。因此,创建了一个新数组,然后将其丢弃。没有其他任何影响。

      您链接到的 wiki 文章显示了稍微不同的陈述:

      self.myArray = [self.myArray arrayByAddingObject:myNewObject];
      

      在这种情况下,生成 KVO 更改通知的是属性的赋值

      要理解的一个重要概念是,KVO 会观察具有该属性更改的属性的对象。在您的情况下,KVO 在您添加观察者时正在观察 self.array 引用的对象。它正在观察其arrayData 属性的变化。

      这很重要的原因是 KVO 观察数组本身。对于许多刚接触 KVO 的人来说,这是一个困惑点。修改数组(例如,如果它是一个可变数组)不会生成任何 KVO 更改通知。

      所有符合 KVO 的更改都必须通过向观察对象发送消息(在您的情况下为self.array)发生。以下是发给self.array 的一些消息,它们会为其arrayData 属性生成更改通知:

      • -setArrayData:,属性设置器。 KVO 使用命名约定识别属性设置器,因此设置器名称的格式必须为 -set<Key>:
      • 因为它显然是一个索引到多关系属性,任何mutable indexed accessors,例如-insertObject:inArrayDataAtIndex:-removeArrayDataAtIndexes:。您需要在具有 arrayData 属性的类上实现此类访问器。如果该属性由NSMutableArray 支持,则这些方法可以简单地传递到NSMutableArray 上的类似方法。
      • 显式调用NSKeyValueObserving informal protocol-willChange...-didChange... 方法,指定@"arrayData" 作为键。通常不鼓励这样做。
      • 使用-setValue:forKey:等KVC方法,指定@"arrayData"为key。只要实例变量被命名为_arrayDataarrayData 并且类方法+accessInstanceVariablesDirectly 没有被覆盖以禁用它,这即使在没有适当的访问器的情况下也可以工作。 真的不鼓励依赖直接实例变量访问,因为它违反了封装性。
      • 使用-mutableArrayValueForKey: 获取属性的KVC 可变数组代理,然后向其发送NSMutableArray 突变方法。这实际上将使用上述机制之一来修改属性,因此它实际上是多余的,但很高兴了解这一点。

      【讨论】:

      • 很好的答案!我会通过这个,试一试,如果我得到它,更新我的问题!谢谢!
      猜你喜欢
      • 1970-01-01
      • 2013-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多