iphone - performSelectorOnMainThread with return value
I have the following method:
- (NSM开发者_高级运维utableArray *)getElements:(NSString *)theURL;
And I wanted to know if there is a way to call that method using performSelectorOnMainThread so that I can get the return value. So far, I've tried with:
myArray = [object performSelectorOnMainThread:@selector(getElements:)
withObject:url waitUntilDone:YES];
but it doesn't work, since performSelectorOnMainThread returns void. How could I solve this?
Welcome to a multi-threaded environment my friend.
You'll need to store the return value in an instance variable or pass in an object by reference through the withObject
parameter:
NSMutableDictionary *myDict;
[object performSelectorOnMainThread:@selector(getElements:)
withObject:&myDict waitUntilDone:YES];
Your method prototype should now look like this:
- (void)getElements:(NSMutableDictionary **)objects;
You can't do it directly, because, as you say, that method returns void.
So, you'd have to arrange another way to get a value back, for example by passing an NSDictionary instead of an NSString, and having the method store the result in the dictionary for you.
Had to implement this recently. Great candidate for adding a category to NSObject so that all your objects can do this:
@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
I have universal solution for async blocking call with return value for any thread, not only main. This example for main thread like 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.
I used this technique only in ARC environment.
精彩评论