2010-07-27 8 views
8

У меня есть следующий метод:iphone - performSelectorOnMainThread с возвращаемым значением

- (NSMutableArray *)getElements:(NSString *)theURL; 

И я хотел бы знать, если есть способ, чтобы вызвать этот метод с использованием performSelectorOnMainThread, так что я могу получить возвращаемое значение. До сих пор, я попытался с:

myArray = [object performSelectorOnMainThread:@selector(getElements:) 
            withObject:url waitUntilDone:YES]; 

, но он не работает, так как performSelectorOnMainThread возвращает ничтожным. Как я могу это решить?

ответ

12

Добро пожаловать в многопоточную среду моего друга.

Вам нужно сохранить возвращаемое значение в переменной экземпляра или передать объект по ссылке через withObject параметра:

NSMutableDictionary *myDict; 

[object performSelectorOnMainThread:@selector(getElements:) 
            withObject:&myDict waitUntilDone:YES]; 

Ваш метод прототип теперь должен выглядеть следующим образом:

- (void)getElements:(NSMutableDictionary **)objects; 
+5

Это не скомпилировано с помощью: «Невозможно инициализировать параметр типа« id »с rvalue типа« NSMutableDictionary ** »« – eodabash

3

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

Итак, вам нужно будет расположить еще один способ вернуть значение, например, передав NSDictionary вместо NSString и имея способ сохранить результат в словаре для вас.

2

Пришлось реализовать это недавно. Великий кандидат для добавления в категорию NSObject так, что все объекты могут сделать это:

@implementation NSObject (CallSelectorWithObjectOnMainThread) 
- (id)resultFromSelectorOnMainThread:(SEL)selector object:(id)object { 
    NSMutableDictionary *resultDictionary = [NSMutableDictionary dictionaryWithCapacity:1]; 
    NSMutableDictionary *callDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:resultDictionary, @"ResultDictionary", NSStringFromSelector(selector), @"Selector", nil]; 
    if(object) [callDict setValue:object forKey:@"Object"]; 
    [self performSelectorOnMainThread:@selector(callObject:) withObject:callDict waitUntilDone:YES]; 
    return [resultDictionary objectForKey:@"Result"]; 
} 

- (void)callObject:(NSMutableDictionary *)info { 
    id result; 
    SEL selector = NSSelectorFromString([info objectForKey:@"Selector"]); 
    id object = [info objectForKey:@"Object"]; 
    NSMutableDictionary *resultDictionary = [info objectForKey:@"Dictionary"]; 
    if(object) 
    result = [self performSelector:selector withObject:object]; 
    else 
    result = [self performSelector:selector]; 
    if(result) 
    [resultDictionary setValue:result forKey:@"Result"]; 
} 
@end 
+0

+1 Спасибо за этот Колин. После использования я обнаружил пару дефектов: callDict необходимо инициализировать с помощью NSMutableDictionary, а callObject должен иметь аргумент метода NSMutableDictionary. – TPoschel

+0

@TPoschel Спасибо! – Colin

2

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

__block id result = nil; 
NSOperationQueue* targetQueue = [NSOperationQueue* mainQueue]; 
// targetQueue is main thread, but it may be queue on any thread. 

[targetQueue addBlockOperation:^{ 
    // performs on target thread. 
    result = [someObject someSelector]; 
}]; 

// wait until operations on targetQueue will finished. 
[targetQueue waitUntilAllOperationsAreFinished]; 

// result is ready here. 

Я использовал эту технику только в среде ARC.

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