4

我试图继承一个 NSOperation,并从中读取一些示例,他们说:当任务完成时,使用 NSOperation 的 KVO 来完成操作,代码在这里:

[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"]
finished = YES;
executing = NO;
[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isExecuting"];

然后 isFinished 被调用

- (BOOL) isFinished{
    return(finished);
}

任何人都可以向我解释这个吗?为什么 isFinished 被调用,isFinished 会完成操作吗?据我了解,KVO 是否需要手动 [self didChangeValueForKey:@"isExecuting"]; 而且我没有看到像 addobserver: 和 observeValueForKeyPath: 这样的代码

我写的

 -(void)call
{
     [self willChangeValueForKey:@"isVip"];
     [self didChangeValueForKey:@"isVip"];
}

-(void)isVip
{
    NSLog(@"Im vip");
}

do [self call]时不调用isVip;

4

3 回答 3

2

NSOperationQueue实现将观察您的操作的“isFinished”属性(使用 KVO),因此它知道何时将其从队列中删除。isFinished最有可能在被告知其值发生变化后被 Apple 内部代码调用。

于 2013-08-27T08:46:19.687 回答
1

添加到平息的答案,这就是你将如何覆盖执行,完成,取消。

//.m
@interface MyOperation ()  //class extension, make these otherwise read-only properties read-write, we must synthesize
@property(atomic, assign, readwrite, getter=isExecuting) BOOL executing;
@property(atomic, assign, readwrite, getter=isFinished) BOOL finished;
@property(atomic, assign, readwrite, getter=isCancelled) BOOL cancelled;
@end

@implementation CoreLocationOperation
@synthesize executing, finished, cancelled;

+ (BOOL)automaticallyNotifiesObserversForKey {
  return YES;
}

+ (NSSet *)keyPathsForValuesAffectingIsCancelled {
  NSSet *result = [NSSet setWithObject:@"cancelled"];
  return result;
}

+ (NSSet *)keyPathsForValuesAffectingIsExecuting {
  NSSet *result = [NSSet setWithObject:@"executing"];
      return result;
}

 + (NSSet *)keyPathsForValuesAffectingIsFinished {
    NSSet *result = [NSSet setWithObject:@"finished"];
   return result;
 }


- (void)start {
 //..
  //You can use self.executing = YES; (note we can change executing which would otherwise be read-only because we synthesized our own ivar.
  [self setExecuting:YES];
...
}

- (void)cancel {
//..
  //super will change the properties executing/finished for us or we can do it manually
  [super cancel];
...

}
    @end

我认为这比拥有更清楚

[self willChangeValueForKey:_NSURLOperationIsFinished];
    [self setIsFinished:YES];
    [self didChangeValueForKey:_NSURLOperationIsFinished];
于 2017-01-28T20:56:55.703 回答
-2

首先,您不需要手动进行 KVO 通知。对于NSOperation子类,应自动发送 KVO 通知,除非您的类通过实施+automaticallyNotifiesObserversForKey+automaticallyNotifiesObserversOf<Key>返回 NO 选择退出自动 KVO 通知。

NSOperation除非将子类添加到NSOperationQueue. 将操作添加到队列时,队列使用 KVO 观察指示状态更改的属性,例如finished, executing,cancelled等。注意这些不是isFinished, isExecuting, 或isCancelled- 这些是这些属性的合成 get 访问器的名称.

在您的问题中,您包含以下代码:

[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"]
finished = YES;
executing = NO;
[self didChangeValueForKey:@"isFinished"];
[self didChangeValueForKey:@"isExecuting"];

您在这里所做的是为 get accessors发送手动 KVO 通知,而不是正在观察的属性。相反,这将完成您似乎正在尝试做的事情:

[self setFinished:YES];
[self setExecuting:NO];

与其直接访问实例变量,不如使用访问器方法。这将正确发送这些属性的自动更改通知。

如果您真的对 KVO 有疑虑并且想要发送获取访问器密钥路径的通知,例如isFinished,请将您的属性注册为密钥路径的依赖项:

+ (NSSet *) keyPathsForValuesAffectingIsFinished {
    NSSet   *result = [NSSet setWithObject:@"finished"];
    return result;
}

注册依赖项是 KVO 合规性的一部分。

于 2014-09-20T21:59:20.753 回答