2013-08-12 1 views
2

Я разрабатываю тестовое приложение, в котором у меня есть NSOperationQueue. Я создаю NSInvocationOperation и наблюдаю за свойством isFinished этой операции. Странно, что watchValueForKeyPath вызывается только иногда. Я не могу понять изменения, которые я должен сделать, чтобы каждый раз его вызывали. Пожалуйста помоги.observValueForKeyPath не называется

Вот код, я написал:

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    ........//initialization 

    queue = [NSOperationQueue new]; 
    operation=[NSInvocationOperation new]; 

    operation = [[NSInvocationOperation alloc]initWithTarget:self  selector:@selector(CreateOperationWithContext:) object:context]; 

    [operation addObserver:self forKeyPath:@"isFinished" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL]; 

    [queue addOperation:operation]; 

    ..... // launch the view controller 
} 

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if ([keyPath isEqualToString:@"isFinished"]) { 
     NSLog(@"came in"); 
     [operation removeObserver:self forKeyPath:@"isFinished"]; 
    } 
    else 
    { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
    } 
} 
+0

Как вы проверяете, когда это так и не вызвано, и такая же проверка в «CreateOperationWithContext»? – Wain

+0

Когда вы не видели уведомление, вы на 100% уверены, что операция была успешно создана, выполнена и завершена, даже если вы все еще не видите 'isFinished' KVN? Например, если он не смог разрешить '@selector (CreateOperationWithContext:)', тогда операция никогда не будет создана в первую очередь. Или, если 'CreateOperationWithContext:' не удалось завершить (бесконечный цикл и т. Д.), Операция также не завершится. Независимо от того, я бы рекомендовал установить 'completionBlock' для вашей операции, а не добавлять наблюдателя для ключа' isFinished'. Это чище и надежнее. – Rob

+0

Привет, Роб и Вайн, Спасибо за ваши ответы. Функция CreateOperationWithContext: вызывается каждый раз и также успешно выполняется. Я обновляю базу данных в функции, и я могу видеть обновление каждый раз. Только наблюдатель не уведомляется. – user2122350

ответ

1

Следующий код работает для меня. Я начал с шаблона приложения iOS Single View. Вот что я имел:

@implementation SOAppDelegate 
{ 
    NSOperationQueue* queue; 
    NSOperation* operation; 
} 

- (void)CreateOperationWithContext: (id)foo 
{ 
    NSLog(@"Op ran"); 
} 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    queue = [NSOperationQueue new]; 
    // operation = [NSInvocationOperation new]; // Commented this out because it's redundant with the next line 
    operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(CreateOperationWithContext:) object:[NSObject new]]; 
    [operation addObserver:self forKeyPath:@"isFinished" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:NULL]; 
    [queue addOperation:operation]; 
    return YES; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if ([keyPath isEqualToString:@"isFinished"]) 
    { 
     NSLog(@"came in"); 
     [operation removeObserver:self forKeyPath:@"isFinished"]; 
    } 
    else 
    { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
    } 
} 

// ... rest of empty default app delegate methods here... 

@end 

В консоли, я вижу:

2013-08-13 08:04:15.150 TestOpKVO[71373:20b] Op ran 
2013-08-13 08:04:21.903 TestOpKVO[71373:20b] came in 

Так что-то о вашей реализации -CreateOperationWithContext: вызывает проблемы. Тем не менее, я по-прежнему вижу, что уведомление KVO вызывается, даже если я изменяю операцию, чтобы исключить исключение.

Если бы я был вами, я бы начал с этого очень простого рабочего примера, а затем продолжил шаг за шагом, чтобы адаптировать его к вашему реальному коду, проверяя каждый шаг, чтобы убедиться, что уведомление все еще работает.

Несколько советов: (которые, вероятно, связаны с проблемой, что вы видите, но хорошая практика для использования КВО)

Во-первых, использовать Кво контексты с наблюдениями. Это безопаснее и детерминированнее. Подробности см. На странице answer I wrote over here.

Во-вторых, не вызывайте -removeObserver:forKeyPath: из-за вызова -observeValueForKeyPath: (или -addObserver:... либо) для той же клавиши, что и уведомление. Это может испортить структуры данных внутреннего наблюдателя KVO и может привести к недетерминированным сбоям, которые могут привести вас в бешенство. Подробности см. На странице answer I wrote over here.

+0

работал, постарается построить на этом. CreateOperationWithcontext обновляет базу данных. Попробуем прервать функцию и тест. спасибо – user2122350

Смежные вопросы