executeSelector в подклассе NSOperation
Я не мог найти ответ где-либо еще в сети, поэтому любая помощь будет оценена.
Я пытаюсь создать систему, с помощью которой я могу получить результаты задачи NSOperation, что, как я понимаю, не может быть выполнено конкретными подклассами, такими как NSInvocation.
У меня есть подкласс NSOperation (TheEngine), который является абстрактным по соглашению и должен быть расширен для реализации функции -main
, чтобы включить тело кода для выполнения.
TheEngine содержит следующую функцию инициализации, работа которой заключается в theSelector
а также theObject
селектор принадлежит. Это также регистрирует наблюдателя KV для собственности isFinished
:
-(id)initWithCallbackSelector:(SEL)theSelector inObject:(id)theObject
В моем observeValueForKeyPath:ofObject:change:context:
Функция Я хотел бы вызвать функцию обратного вызова, например, так:
NSLog(@"Some debug text to ensure this function is being called", nil);
[theObject performSelector:theSelector withObject:someData afterDelay:0];
Весь процесс выглядит так:
aViewController запускает расширение TheEngine - скажем, TheTask, вызывая следующее и добавляя его в очередь операций.
TheTask* TT = [[TheTask alloc] initWithCallbackSelector:
@selector(resultHandler:) inObject:theObject];
Кажется, все работает, как и ожидалось, без каких-либо ошибок или исключений. Но когда исполнение достигает observeValueForKeyPath:ofObject:change:context:
обратный вызов на самом деле не вызывается. Я новичок в Obj-C, поэтому я не совсем уверен, правильно ли я понимаю этот тип потоков.
Вот весь код:
-(id)initWithCallbackSelector:(SEL)theSelector inObject:(id)theObject{
if([self init]){
self.selectorsParentObject = theObject;
self.selectorToCallWhenFinished = theSelector;
[self addObserver:self forKeyPath:@"isFinished" options:NSKeyValueObservingOptionNew context:NULL];
return self;
}
return nil;
}
-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)theObject change:(NSDictionary*)theChange context:(void*)theContext{
if([keyPath isEqualToString:@"isFinished"]){
NSLog(@"activity is finished with change: %@", theChange);
NSLog(@"target object: %@", self.selectorsParentObject);
NSLog(@"target selector: %@", NSStringFromSelector(self.selectorToCallWhenFinished));
//[self performSelectorOnMainThread:self.selectorToCallWhenFinished withObject:self.resultData waitUntilDone:NO];
[self.selectorsParentObject performSelector:@selector(selectorToCallWhenFinished) withObject:self.resultData afterDelay:0];
}
}
Любая помощь приветствуется!
2 ответа
Ваш NSOperation
скорее всего работает в фоновом потоке. Если этот поток пропадает, или если этот поток не может прокачать цикл выполнения, тогда ваш вызов performSelector:withObject:afterDelay:
не будет стрелять Вы прокомментировали звонок performSelectorOnMainThread:...
, Это сработало?
Вы, вероятно, должны запустить это в главном потоке или запустить это с performSelector:withObject:
(без afterDelay:
). performSelector:withObject:
не требует цикла выполнения.
Как предположил Роб, код выполнялся в фоновом потоке, как и вызов observeValueForKeyPath:ofObject:change:context:
Первоначально я изменил код так, чтобы селектор был запущен в главном потоке с [self performSelectorOnMainThread:@selector(runCallback) withObject:nil waitUntilDone:NO];
,
Но в этом случае основным потоком оказывается TheTask, и было выдано исключение, поскольку TheTask не принадлежит theSelector
, Чтобы исправить это, я создал дополнительную функцию -runCallback
и выстрелил из
-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)theObject change:(NSDictionary*)theChange context:(void*)theContext{
if([keyPath isEqualToString:@"isFinished"]){
NSLog(@"activity is finished with change: %@", theChange);
NSLog(@"target object: %@", self.selectorsParentObject);
NSLog(@"target selector: %@", NSStringFromSelector(self.selectorToCallWhenFinished));
[self performSelectorOnMainThread:@selector(runCallback) withObject:nil waitUntilDone:NO];
//[self performSelectorOnMainThread:self.selectorToCallWhenFinished withObject:self.resultData waitUntilDone:NO];
//[self.selectorsParentObject performSelector:@selector(selectorToCallWhenFinished) withObject:self.resultData afterDelay:0];
}
}
и в -runCallback
:
-(void)runCallback{
[self.selectorsParentObject performSelector:self.selectorToCallWhenFinished withObject:self.resultData afterDelay:0];
}
Это называется theSelector
в TheTask с правильными данными. Спасибо за участие:)