Tutorial :iphone - performSelectorOnMainThread with return value



Question:

I have the following method:

- (NSMutableArray *)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?


Solution:1

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;  


Solution:2

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.


Solution:3

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.


Solution:4

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  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »