NSOperation KVO isFinished

前提是你 提交于 2019-12-05 14:31:54

The NSOperationQueue implementation will observe the "isFinished" property of your operation (using KVO) so it knows when to remove it from the queue. isFinished is most likely being called by internal Apple code after it has been told of the change to its value.

Adding to quellish answer, this is how you would override executing, finished, cancelled.

//.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

I think this is clearer than having

[self willChangeValueForKey:_NSURLOperationIsFinished];
    [self setIsFinished:YES];
    [self didChangeValueForKey:_NSURLOperationIsFinished];

First, you should not need to do manual KVO notifications. For an NSOperation subclass KVO notifications should be sent automatically unless your class has opted out of automatic KVO notifications by implementing +automaticallyNotifiesObserversForKey or +automaticallyNotifiesObserversOf<Key> to return NO.

NSOperation subclasses are not very useful unless they are added to an NSOperationQueue. When an operation is added to a queue, the queue uses KVO to observe the properties that indicate state changes, such as finished, executing, cancelled, etc. Note that these are not isFinished, isExecuting, or isCancelled - those are the names of the synthesized get accessors for those properties.

In your question you include this code:

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

What you're doing here is sending manual KVO notifications for the get accessors, not the properties being observed. Instead, this would accomplish what you seem to be trying to do:

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

Rather than accessing instance variables directly, use the accessor methods. This will correctly send automatic change notifications for these properties.

If you are truly paranoid about KVO and want to send notifications for the get accessor key paths such as isFinished, register your property as a dependency of the key path:

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

Registering dependencies is part of KVO compliance.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!