Учтите это:
@interface SomeViewController : UIViewController {
SomeChildObject *child;
}
@end
@implementation SomeViewController
- (void) viewDidLoad {
...
child.delegate = self;
}
- (void) somethingHappened {
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:child
selector:@selector(doSomething)
object:nil];
[someNsOperationQueue addOperation:operation];
[operation release];
}
- (void) callbackA:(SomeData *)someData {
[self performSelectorOnMainThread:@selector(callbackAonMainThread:)
withObject:someData
waitUntilDone:NO];
}
- (void) callbackAonMainThread:(SomeData *)someData {
... do something with results in main thread, e.g UI feedback
}
- (void) callbackB:(SomeData *)someData {
[self performSelectorOnMainThread:@selector(callbackBonMainThread:)
withObject:someData
waitUntilDone:NO];
}
- (void) callbackBonMainThread:(SomeData *)someData {
... do something with results in main thread, e.g UI feedback
}
@end
На английском языке:
У меня есть контроллер представления, работающий в главном потоке с объектом дочерней модели, чтобы что-то делать (получать данные по сети). Контроллер представления является делегатом для дочернего элемента, поэтому дочерний элемент может передать результаты обратно с делегированием. Чтобы выполнить дорогостоящую работу, я породил метод child.doSomething с NSInvocationOperation, который запускает операцию в фоновом потоке. Когда это сделано, дочерний процесс вызывает callbackA или callbackB делегата (контроллера представления) с некоторыми результатами. Поскольку (я думаю) эти обратные вызовы вызываются в том же фоновом потоке, где был запущен вызов doSomething, мне нужно вызвать executeSelectorOnMainThread для передачи управления обратно в основной поток.
Это прекрасно работает, но мне не нравится иметь два метода, связанных с обратным вызовом, для каждого обратного вызова. (На самом деле существует больше обратных вызовов, поэтому реальный код еще более раздут.) В идеале я бы сделал что-то вроде этого:
- (void) callbackA:(SomeData *)someData {
if (not_running_on_main_thread) {
[self performSelectorOnMainThread:@selector(callbackA:)
withObject:someData
waitUntilDone:NO];
} else {
// now running on main thread, work with the results.
}
}
Вопросы:
1) как мне выполнить тест not_running_on_main_thread?
2) есть ли какой-нибудь другой способ сократить количество обратных вызовов?
РЕДАКТИРОВАТЬ: хорошо, я никогда не читал документы NSThread перед публикацией :) похоже, что [NSThread isMainThread] это то, что я ищу. Но есть ли другой способ реструктурировать или сделать это еще лучше?