问题描述
在使用自定义的NSOperation
子类时,我注意到[NSOperation automaticallyNotifiesObserversForKey]
类方法(至少对于某些键路径返回NO
)禁用了自动键值观察.因此,NSOperation
子类内部的代码会被手动调用willChangeValueForKey:
和didChange…
乱扔,这在网络上的许多代码示例中都是可见的.
When working with a custom NSOperation
subclass I noticed that the automatic key-value observing is disabled by the [NSOperation automaticallyNotifiesObserversForKey]
class method (which returns NO
at least for some key paths). Because of that the code inside of NSOperation
subclasses is littered by manual calls to willChangeValueForKey:
and didChange…
, as visible in many code samples on the web.
为什么NSOperation
那样做?使用自动KVO支持,人们可以简单地声明操作生命周期标志(isExecuting
等)的属性,并通过访问器触发KVO事件,即.以下代码:
Why does NSOperation
do that? With automatic KVO support people could simply declare properties for the operation lifecycle flags (isExecuting
etc.) and trigger the KVO events through the accessors, ie. the following code:
[self willChangeValueForKey:@"isExecuting"];
executing = NO;
[self didChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];
...可以替换为:
[self setIsExecuting:NO];
[self setIsFinished:YES];
在某处有陷阱吗?我只是改写了automaticallyNotifiesObserversForKey
以返回YES
,而且一切似乎正常.
Is there a catch somewhere? I just overrode the automaticallyNotifiesObserversForKey
to return YES
and things seem to work fine.
推荐答案
最可能的解释是kvo键与标准约定不匹配.通常,其中一种方法具有-isExecuting
和-setExecuting:
之类的键路径为@"executing"
的方法.在NSOperation的情况下,密钥路径改为@"isExecuting"
.
The most likely explanation is that the kvo keys don't match the standard conventions. Normally one has methods like -isExecuting
and -setExecuting:
, where the key path is @"executing"
. In the case of NSOperation, the key path is @"isExecuting"
instead.
另一种可能性是,大多数NSOperations实际上没有名为-setIsExecuting:
的方法来更改该值.相反,它们将执行/完成标志基于其他内部状态.在这种情况下,绝对需要使用显式的willChange/didChange通知.例如,如果我有一个包裹NSURLConnection的NSOperation,则我可能有2个ivars,一个名为data
的目录,它保存下载的数据,一个名为connection
的目录,它存储NSURLConnection,我可以这样实现getter:
The other possibility is that most NSOperations don't actually have a method named -setIsExecuting:
to change that value. Instead, they base the executing/finished flags on other internal state. In this case, one absolutely needs to use the explicit willChange/didChange notifications. For example, if I have an NSOperation that wraps an NSURLConnection, I may have 2 ivars, one named data
that holds the downloaded data, and one named connection
which holds the NSURLConnection, and I may implement the getters like so:
- (BOOL)isExecuting {
return (connection != nil);
}
- (BOOL)isFinished {
return (data != nil && connection == nil);
}
现在我的-start
方法可以使用
[self willChangeValueForKey:@"isExecuting"];
data = [[NSMutableData alloc] init]; // doesn't affect executing, but is used later
connection = [[NSURLConnection connectionWithRequest:request delegate:self] retain];
[self didChangeValueForKey:@"isExecuting"];
开始执行,
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
[connection cancel];
[connection release];
connection = nil;
[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isExecuting"];
完成.
这篇关于为什么NSOperation禁用自动键值观察?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!