我正在通过“更多iPhone 3开发”的并发章节中的一个示例,并且无法使NSOperationQueue
的KVO按预期工作。我创建了一个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),因此,在更改字典中,查找从NSKeyValueChangeKindKey
到NSKeyValueChangeInsertion
的映射,以及从NSKeyValueChangeNewKey
到添加的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
的子类,它恰当地覆盖了main
,而Stalled
只是项目名称。)但请注意,该方法被调用两次插入单个操作,并且两次都具有类值1,即NSKeyValueChangeSetting
,而不是NSKeyValueChangeInsertion
。此外,newValue
和oldValue
似乎是数组本身,而不是添加的项目。
有什么想法吗?谢谢!
答案 0 :(得分:3)
文档说-operations
符合KVO标准,但未指定通知的详细信息。在实践中,似乎只告诉您发生了更改,因此必须比较旧值和新值以找出插入的内容。
不要忘记这些通知可以通过任何线程发送给您!
答案 1 :(得分:-1)
NSOperationQueue的operations属性没有可变类型(返回NSArray*
)。因此,它不会为可变数组实现索引到多个合规性方法,因此您永远不会看到插入事件,只看到整个数组的更改事件。
修改强>
Shadowmatter提出了实际返回的对象是NSMutableArray
的事实。但是,这并没有改变任何事情。首先,Apple's documentation在这个问题上是明确的。如果通告方法返回不可变对象,则必须遵守API。你不能使用isKindOf:
来确定它是否真的可变,你绝对不能改变它。
API表示操作返回类型是不可变的,因此您必须将其视为不可变。更重要的是,对于这个问题,由于它不是可变的集合属性,因此可变数组KVC值不是key value coding compliant。对于可变索引集合合规性,该类必须
- 实施一种或两种方法
-insertObject:in<Key>AtIndex:
或-insert<Key>:atIndexes:
。- 实施一种或两种方法
-removeObjectFrom<Key>AtIndex:
或-remove<Key>AtIndexes:
。
(直接取自Apple KVC指南)
NSOperationQueue
类的设计者将operations
属性设计为不可变,因此故意省略上述方法。