Run method on main thread from another thread
Asked Answered
P

1

8

My model class has to get some data from the internet. So I decided to run it on another thread so the ui doesn't freeze. So when an object wants some data it first asks the model using a method of this type:

- (void)giveMeSomeData:(id)object withLabel:(id)label {
objectAsking= object;
theLabel= label;
NSThread* thread= [[NSThread alloc] initWithTarget:self selector:@selector(getTheDataFromInternet) object:nil];
[thread start];
}

- (void)getTheDataFromInternet {
//getting data...

theData= [dataFromInternet retain]; //this is the data the object asked for
[self returnObjectToAsker];
}

- (void)returnObjectToAsker {
[objectAsking receiveData:theData withLabel:theLabel];
}

As I'm still a newbie, can you tell me if it's a good pattern?

Thanks!

Professed answered 3/2, 2011 at 21:56 Comment(4)
Don't forget to release what you create, in accordance with the memory management rules. developer.apple.com/mac/library/documentation/Cocoa/Conceptual/… From the code you showed, you should own and, if not running under GC, eventually release both thread and theData.Shaunta
Also, it sounds like getTheDataFromInternet does so synchronously. Don't do that—you'll block your UI for however many milliseconds/seconds/minutes/hours/days it takes to get the data. It doesn't matter how small it is, or how awesome your own internet connection is—your users will see your app lock up while it waits for the data. Instead, create (and own) an NSURLConnection to receive asynchronously: developer.apple.com/mac/library/documentation/Cocoa/Reference/… Report the progress using (at least) an NSProgressIndicator.Shaunta
Of course, I decided not to write these lines for the sake of clarity ;)Professed
About the synchronous/asynchronous network calls: this is why I want to implement multi-threading. I want to make synchronous calls in a different thread.Professed
S
14

Your setup is pretty much correct. You never want to initiate any sort of network connection on the main thread.

As it currently stands, -returnObjectToAsker will be executed on the background thread.

You'd probably be interested in -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:].

Or if you wanted to something with Grand Central Dispatch (iOS 4+, Mac OS X 10.6+), you could do:

#import <dispatch/dispatch.h>

- (void)giveMeSomeData:(id)object withLabel:(id)label {
    dispatch_async(dispatch_get_global_queue(0,0), ^{
      //this runs on a background thread
      //get data from the internet
      dataFromTheInternet = ...;
      dispatch_async(dispatch_get_main_queue(), ^{
        [object receiveData:dataFromTheInternet withLabel:label];
        //this runs on the main thread.  Use theData
      });
    });
}

Since the blocks capture their environment, you wouldn't even have to save off object and label into ivars. :)

Shrimp answered 3/2, 2011 at 22:1 Comment(2)
Thank you for your quick answer :) What do you prefer, GCD or using NSThread?Professed
@Forchita if I can get away with only supporting iOS 4 or OS 10.6, then I prefer to use GCD because I can keep all the logic in a single method.Shrimp

© 2022 - 2024 — McMap. All rights reserved.