3

我正在研究“更多 iPhone 3 开发”的并发章节中的一个示例,并且无法让 KVONSOperationQueue按预期工作。我创建一个NSOperationQueue并使用以下方法观察它的operations数组:

NSOperationQueue *newQueue = [[NSOperationQueue alloc] init];
self.queue = newQueue;
[newQueue release];
[queue addObserver:self
        forKeyPath:@"operations"
           options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
           context:NULL];

当第一个NSOperation被添加到队列中时,我希望它被添加到它的底层operations数组(iOS 文档说它是 KVO 兼容的),因此,在更改字典中,找到一个映射 from NSKeyValueChangeKindKeyto NSKeyValueChangeInsertion,以及一个映射 fromNSKeyValueChangeNewKey添加到NSOperation. 但我没有看到任何价值NSKeyValueChangeInsertion

我知道调试器是专业的,但是为了在这里复制一些有用的东西,我开始了我的观察者方法:

- (void) observeValueForKeyPath:(NSString *)keyPath
                       ofObject:(id)object
                         change:(NSDictionary *)change
                        context:(void *)context {
  NSNumber *kind = [change objectForKey:NSKeyValueChangeKindKey];
  NSObject *newValue = [change objectForKey:NSKeyValueChangeNewKey];
  NSObject *oldValue = [change objectForKey:NSKeyValueChangeOldKey];
  NSIndexSet *indexes = [change objectForKey:NSKeyValueChangeIndexesKey];
  NSLog(@"kind=%d, newValue=%@, oldValue=%@, indexes=%@",
       [kind integerValue], newValue, oldValue, indexes);

那打印:

2010-11-18 20:01:56.249 Stalled[2692:6f07] kind=1, newValue=(
    "<SquareRootOperation: 0x5f51b40>"
), oldValue=(
), indexes=(null)

2010-11-18 20:01:56.250 Stalled[2692:6f07] kind=1, newValue=(
    "<SquareRootOperation: 0x5f51b40>"
), oldValue=(
    "<SquareRootOperation: 0x5f51b40>"
), indexes=(null)

SquareRootOperation只是我适当NSOperation覆盖的子类,并且只是项目名称。)但请注意,该方法在插入单个操作时被调用两次,并且两次都使用 kind 值 1,即not 。此外,似乎是数组本身,而不是添加的项目。mainStalledNSKeyValueChangeSettingNSKeyValueChangeInsertionnewValueoldValue

有任何想法吗?谢谢!

4

2 回答 2

3

The docs say -operations is KVO-compliant, but don't specify to what detail the notifications will be. In practice, it seems you are only told that a change has occurred, so would have to compare the old and new values to find out what was inserted.

Don't forget that these notifications can be sent to you on any thread!

于 2010-12-23T17:54:22.030 回答
-1

NSOperationQueue 的操作属性没有可变类型(它返回NSArray*)。因此,它没有为可变数组实现多索引合规方法,因此您永远不会看到插入事件,只会看到整个数组的更改事件。

编辑

Shadowmatter 提出了一个事实,即实际返回的对象是一个NSMutableArray. 然而,这并没有改变任何东西。首先,Apple 的文档在这个问题上很清楚。如果一个方法被宣传为返回一个不可变对象,您必须遵守 API。你千万不能用isKindOf:它来判断它是否真的是可变的,你绝对不能改变它。

API 说操作返回类型是不可变的,因此您必须这样对待它。对于这个问题更重要的是,由于它不是可变集合属性,因此它不符合可变数组 KVC 值的键值编码。对于可变索引集合合规性,该类必须

  • 实现一种或两种方法-insertObject:in<Key>AtIndex:-insert<Key>:atIndexes:.
  • 实现一种或两种方法-removeObjectFrom<Key>AtIndex:-remove<Key>AtIndexes:.

(直接取自 Apple KVC 指南)

NSOperationQueue该类的设计者将属性设计operations为不可变的,因此故意省略了上述方法。

于 2010-11-19T11:18:09.770 回答