首页 文章

NSOperation KVO完成

提问于
浏览
3

我试图对一个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");
}

[自我呼叫]时不调用isVip;

3 回答

  • -2

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

  • 1

    添加到quellish的答案,这是你如何覆盖执行,完成,取消 .

    //.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];
    
  • 2

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

    除非将子类添加到 NSOperationQueue ,否则 NSOperation 子类不是很有用 . 将操作添加到队列时,队列使用KVO来观察指示状态更改的属性,例如 finishedexecutingcancelled 等 . 请注意,这些不是 isFinishedisExecutingisCancelled - 这些是合成获取这些属性的访问器 .

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

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

    你在这里做的是为get访问者发送手动KVO通知,而不是观察到的属性 . 相反,这将完成你似乎想要做的事情:

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

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

    如果您是关于KVO的 truly paranoid 并且想要发送get访问者密钥路径(例如 isFinished )的通知,请将您的属性注册为密钥路径的依赖项:

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

    Registering dependencies is part of KVO compliance.

相关问题