首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么NSOperation会禁用自动键值观察?

为什么NSOperation会禁用自动键值观察?
EN

Stack Overflow用户
提问于 2010-08-26 16:15:31
回答 2查看 4.3K关注 0票数 20

在使用自定义NSOperation子类时,我注意到[NSOperation automaticallyNotifiesObserversForKey]类方法禁用了自动键值观察(它至少为某些键路径返回NO )。正因为如此,NSOperation子类中的代码被手动调用willChangeValueForKey:didChange…弄得乱七八糟,这在web上的许多代码示例中都可以看到。

为什么NSOperation要这么做?有了自动KVO支持,人们可以简单地声明操作生命周期标志(isExecuting等)的属性。并通过访问器触发KVO事件,即。以下代码:

代码语言:javascript
复制
[self willChangeValueForKey:@"isExecuting"];
executing = NO;
[self didChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];

…可以替换为以下内容:

代码语言:javascript
复制
[self setIsExecuting:NO];
[self setIsFinished:YES];

在什么地方有陷阱吗?我刚刚重写了automaticallyNotifiesObserversForKey以返回YES,一切似乎都很正常。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-01-21 12:57:58

最可能的解释是kvo密钥与标准约定不匹配。通常有像-isExecuting-setExecuting:这样的方法,其中关键路径是@"executing"。在NSOperation的情况下,密钥路径改为@"isExecuting"

另一种可能是大多数NSOperations实际上没有名为-setIsExecuting:的方法来更改该值。相反,它们将执行/完成标志建立在其他内部状态的基础上。在这种情况下,绝对需要使用显式的willChange/didChange通知。例如,如果我有一个包装NSURLConnection的NSOperation,我可能有两个ivar,一个名为data的保存下载的数据,一个名为connection的保存NSURLConnection,我可以像这样实现getter:

代码语言:javascript
复制
- (BOOL)isExecuting {
    return (connection != nil);
}

- (BOOL)isFinished {
    return (data != nil && connection == nil);
}

现在我的-start方法可以使用

代码语言:javascript
复制
[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"];

开始执行,并且

代码语言:javascript
复制
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
[connection cancel];
[connection release];
connection = nil;
[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isExecuting"];

来完成。

票数 17
EN

Stack Overflow用户

发布于 2017-08-02 14:31:39

我不知道你为什么要说NSOperation不能使用自动KVO。但我只是尝试验证这一点,因此它可以使用KVO。

代码语言:javascript
复制
[self addObserver:self
       forKeyPath:@"isReady"
          options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
          context:&ctxKVO_CSDownloadOperation];

[self addObserver:self
       forKeyPath:@"isExecuting"
          options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
          context:&ctxKVO_CSDownloadOperation];

[self addObserver:self
       forKeyPath:@"isFinished"
          options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
          context:&ctxKVO_CSDownloadOperation];

[self addObserver:self
       forKeyPath:@"isCancelled"
          options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
          context:&ctxKVO_CSDownloadOperation];

...

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == &ctxKVO_CSDownloadOperation) {
        NSLog(@"KVO: %@", keyPath);
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

结果是:

代码语言:javascript
复制
2017-08-02 14:29:58.831 CSDownloader[77366:5089399] isReady : 1
2017-08-02 14:29:58.831 CSDownloader[77366:5089399] KVO: isReady
2017-08-02 14:29:58.831 CSDownloader[77366:5089399] isExecuting : 0
2017-08-02 14:29:58.831 CSDownloader[77366:5089399] KVO: isExecuting
2017-08-02 14:29:58.831 CSDownloader[77366:5089399] isFinished : 0
2017-08-02 14:29:58.832 CSDownloader[77366:5089399] KVO: isFinished
2017-08-02 14:29:58.832 CSDownloader[77366:5089399] isCancelled : 0
2017-08-02 14:29:58.832 CSDownloader[77366:5089399] KVO: isCancelled
2017-08-02 14:29:58.832 CSDownloader[77366:5089399] isReady : 1
2017-08-02 14:29:58.832 CSDownloader[77366:5089399] KVO: isReady
2017-08-02 14:29:58.833 CSDownloader[77366:5089399] isExecuting : 0
2017-08-02 14:29:58.833 CSDownloader[77366:5089399] KVO: isExecuting
2017-08-02 14:29:58.833 CSDownloader[77366:5089399] isFinished : 0
2017-08-02 14:29:58.833 CSDownloader[77366:5089399] KVO: isFinished
2017-08-02 14:29:58.833 CSDownloader[77366:5089399] isCancelled : 0
2017-08-02 14:29:58.833 CSDownloader[77366:5089399] KVO: isCancelled
2017-08-02 14:29:58.834 CSDownloader[77366:5089399] isReady : 1
2017-08-02 14:29:58.834 CSDownloader[77366:5089399] KVO: isReady
2017-08-02 14:29:58.834 CSDownloader[77366:5089399] isExecuting : 0

所以我真的对这个问题和答案感到困惑。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3573236

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档