2013-08-27 2 views
3

Im пытается создать подкласс NSOperation, и прочитать некоторые образцы из, они говорят: когда задача закончена, используя КВО из NSOperation, чтобы завершить операцию, код здесь:NSOperation KVO isFinished

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

затем isFinished get called

- (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 не вызывается, когда сделать [самостоятельный вызов];

ответ

2

Реализация NSOperationQueue будет выполнять функцию «isFinished» вашей операции (используя KVO), поэтому она знает, когда ее удалить из очереди. isFinished, скорее всего, вызывается внутренним кодом Apple после того, как ему сообщили об изменении его значения.

+0

, как и когда делает dealloc FUNC работы можно назвать? – nickyu

+0

'dealloc' вызывается, когда счетчик ссылок операции достигает 0, т. Е. Когда у кого-то нет ссылки на него. –

+0

cool, man, я даю операцию наблюдателю, а когда isFinished, я вызываю release и dealloc. Большое спасибо, – nickyu

-2

Во-первых, вам не нужно делать ручные уведомления KVO. Для подкласса NSOperation уведомления KVO должны отправляться автоматически, если ваш класс не отказался от автоматических уведомлений KVO, внедрив +automaticallyNotifiesObserversForKey или +automaticallyNotifiesObserversOf<Key>, чтобы вернуть NO.

NSOperation Подклассы не очень полезны, если они не добавлены к NSOperationQueue. Когда операция добавляется в очередь, очередь использует KVO для наблюдения за свойствами, которые указывают изменения состояния, такие как finished, executing, cancelled и т. Д. Обратите внимание, что это не isFinished, isExecuting, или isCancelled - это имена синтезированные get accessors для этих свойств.

В своем вопросе вы включили этот код:

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

Что вы делаете здесь отправки уведомлений вручную КВО для ГЭТ Accessors, а не свойства наблюдается. Вместо этого достичь бы то, что вы, кажется, пытаются сделать:

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

Вместо того, чтобы обращающиеся переменные экземпляра непосредственно, использовать методы доступа. Это будет правильно отправлять автоматические уведомления об изменениях для этих свойств.

Если вы действительно параноик о КВО и хотите отправлять уведомления для ГЭТ аксессоры ключевых путей, таких как isFinished, зарегистрировать свою собственность как зависимость ключевого пути:

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

Registering dependencies is part of KVO compliance.

+0

Это неверно. Я бы назвал читателей нашей дискуссией в комментариях http://stackoverflow.com/a/25953779/1271826. – Rob

+0

Исходный подход автора к ручному вызову методов уведомления KVO заключается в попытке управлять зависимостями между путями ключей. У KVO есть механизм для этого, который должен использоваться в качестве первого курорта. – quellish

+0

Хорошее добавление шаблона зависимостей ключевых путей для получения требуемых «isFinished» (и других) уведомлений. – Rob

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]; 
Смежные вопросы