Recommended thread layer to use for iPhone development? - iphone

I'm new to Objective C, and Mac development... It appears that I can use the Posix threads API in my app.. Is this the recommended way? Or is their some Apple API I should be using for mutexes, condition variables and threads instead?
I should add that I'm developing for the iPhone.
I'd like to add exactly what I'm trying to do. Basically, CoreLocation is asynchronous... You tell it to start updating you, and then it just calls an update method on you periodically...
The problem I have is that I need another thread to block until an update occurs... How can I make the main application thread block until at least one CoreLocation update occurs? Is their an NSConditionVariable? :)

I'd suggest an even easier way to get stuck into threads is to use the following call:
[self performSelectorInBackground:(#selector(myMethod)) withObject:nil];
This will automatically create a new background thread for you to run in. Incidentally make sure you do the following inside your background method:
-(void) myMethod {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// code you want to run in background thread;
[pool drain];
}
This is necessary because there isn't a default autorelease pool set up for any threads except the main one.
Finally, talking about blocking the main thread, you could use the following from your background thread to do this:
[self performSelectorOnMainThread:(#selector(myOtherMethod)) withObject:nil waitUntilDone:YES];
The optional third parameter will hold up the main thread for you if you want it to do so.
Hope that helps!

It depends on what you are trying to do, but I would start with NSOperation and NSOperationQueue. It makes it pretty simple to hand off background tasks. Take a look at Dave Dribin's blog post on NSOperation concurrency as well: http://www.dribin.org/dave/blog/archives/2009/05/05/concurrent_operations/

Instead of blocking the user interface by making it hang, I would suggest showing some kind of loading screen until you've received your first update. The could would look something like this:
- (void)viewDidLoad {
...
[myCLLocationManager beginUpdates];
[self showLoadingIndicator];
....
}
- (void)locationManager:(CLLocationManager *)manager didReceiveUpdates {
[self hideLoadingIndicator];
// Additionally load the rest of your UI here, if you haven't already
}
Don't quote me on those method calls verbatim, but that's how I suggest solving your problem, in essence.

Yes there is an NSCondition object, and it will probably do exactly what you want for the CoreLocation scenario you mentioned.

Related

MBProgressHUD issue in main thread.

I would like to use MBProgressHUD the following way: In my method I call multiple servers and other actions that require showing a HUD. I was wondering what would be the best way to "hold" the main thread until those particular actions are done.
For example:
method {
MBProgressHUD (action 1) //don't move on until this is done
//some other code...
MBProgressHUD (action 2)
//some other code...
}
I am pretty new to iOS so sorry if this is too simple. thank you.
I think you use graphical change in MBProgressHUD.
example :-
[HUD showWhileExecuting:#selector(fetchNewData) onTarget:self withObject:nil animated:YES];
fetchNewData will be called on secondary thread . so no use graphical change in MBProgressHUD.
if you want to graphical change use in hudWasHidden delegete
You may take a look at this answer, or ask the developer over at Github. Also, it is never a good idea to block the main-thread. Call it in a different thread. Go for Grand Central Dispatch.

iphone - what is the logic of this kind of multithread operation

I am just trying to understand this: multithread is a way of firing a method in another thread, so it will not hang the main thread (when something heavy must be done). But I have seen stuff like this:
this goes on the main code:
[NSThread detachNewThreadSelector:#selector(createNewThread) toTarget:self withObject:nil];
and here goes the thread
-(void) createNewThread {
NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init];
[self performSelectorOnMainThread:#selector(doSomeStuff) withObject:nil waitUntilDone:YES];
[p release];
}
My problem with this is: if the thread is intended to relieve the main thread from doing something, why is doSomeStuff being called using performSelectorOnMainThread? Isn't that insane? I mean, you fire a second thread just to run something on the main thread, a thread that in fact you shouldn't be using.
I have seen a lot of code on the web write this way.
I know that probably it is done that way because it is doing something that is not thread safe, but is doing this really useful? To me sounds that it is totally useless and it would be better to do something like
[self performSelector:#selector(doSomeStuff) withObject:nil afterDelay:0.01];
what do you guys think?
thanks in advance.
performSelectorOnMainThread:withObject:waitUntilDone: puts the call on a queue to perform on the next iteration of the run loop. performSelector:withObject:afterDelay: sets up a timer to perform the action. However, creating a new thread to call performSelectorOnMainThread makes no sense because it puts the call on the queue even if it is already on the main thread.
If that's the entire body of the createNewThread method then it makes no sense. But if other stuff actually happens in createNewThread then there might be a good reason. The most common scenario for having a background thread use performSelectorOnMainThread: is if the UI needs to update as a result of the background activity. Like if you're processing a large data set and you want to show the user how much progress has been made so far. UIKit is not thread-safe so you can't update the UI from the background thread. But you might do something like, have the background doing a lot of work in a loop, and at every pass through the loop (or every 5, or whatever) call back to the main thread to update the UI. This makes the code switch back to the main loop just long enough to update the UI before returning to the background for the heavy duty work.

iPhone SDK Background threads calling other methods

I am a seemingly straightforward question that I can't seem to find an answer to (and it is hindering my app).
I have a background thread running a paricular method:
-(void)processImage:(UIImage *)image {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//Process image here in the background here
[pool drain];
}
This much works great, but my question comes when I want to call another method from inside the already-background method. Does this call stay in the background? Do I need to add NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; and [pool drain]; to the new method to make it run in the background as well?
Any advice would be very helpful. I am a bit confused about this.
Many thanks,
Brett
It WILL stay in the background, on the same thread it was called from.
Some threading notes to consider with this:
It may not be obvious, but if you call a timer from the background thread, and the thread exits before the timer is supposed to go off, the timer will NOT be called. Thus it is recommended you setup timers from the main thread
You dont need another autorelease pool unless you spawn another thread.
Any UI updates should be done on the main thread
You don't need to add yet another autorelease pool, the one you already have is enough. And yes, all calls that you make that originate from that thread stay in that thread and thus also run "in the background". Exception would be the use of "performSelectorOnMainThread:", which of course makes the given selector to be performed on the main thread :-) If you want to call GUI methods (like setting the image on an UIImageView) you should make sure to do so on the main thread. See the docs for "performSelectorOnMainThread:waitUntilDone:" (sorry for not giving you you the links, am typing this on my iPad).

NSThread terminating too early

I have an app that uploads to Google Spreadsheets via the GData ObjC client for Mac/iPhone. It works fine as is. I'm trying to get the upload portion on its own thread and I'm attempting to call the upload method on a new thread.
Look:
-(void)establishNewThreadToUpload {
[NSThread detachNewThreadSelector:#selector(uploadToGoogle) toTarget:self withObject:nil];
}
-(void)uploadToGoogle {
NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];
//works fine
[helper setNewServiceWithName:username password:password];
//works fine
[helper fetchUserSpreadsheetFeed];
//inside the helper class, fetchUserSpreadsheet feed calls ANOTHER method, which
//calls ANOTHER METHOD and so on, until the object is either uploaded or fails
//However, once the class gets to the end of fetchUserSpreadsheetFeed
//control is passed back to this method, and
[pool release];
//is called. The thread terminates and nothing ever happens.
}
If I forget about using a separate thread, everything works like it's supposed to. I'm new to thread programming, so if there's something I'm missing, please clue me in!
Thanks!
I've had this problem and I have a solution, however, the solution kind of makes me cringe as it works, but something smells about it... it seems like their should be a better way.
I suspect somewhere within [helper fetchUserSpreadsheetFeed] you are using some form of NSURLConnection. If you are using an asynchronous http request (where you setup the delegate for callback functions and such) the thread may terminate before the connection has a chance to invoke those callback functions and silently fail. Here's my solution which keeps the thread alive until the callbacks set a 'finished' variable to YES. (I also seem to have trouble posting code in these text boxes so if those angels that run around editing stuff can help me out that'd be great!)
- (void)fetchFeed {
//NSLog(#"making request");
[WLUtilities makeHttpRequest:self.feedUrlString withHttpHeaders:nil withDelegate:self];
//block this thread so it's still alive when the delegates get called
while(!finished) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
The problem I have with this solution is that spinning while loops are generally not good practice. I'm not sure as to the nature of the runloop business though, it may be properly sleeping and stuff but I'm not sure.
At any rate, you could give that a try and see what happens!
NOTE: my "WLUtilities" function is just a wrapper around the NSURLConnection function to create an asynchronous http request. Another solution you might try is simply using a synchronus request but I don't like this solution much either because the asynchronous call offers finer grained control over the connection.
Use the techniques in this answer:
How can I upload a photo to a server with the iPhone?

Difference between [NSThread detachNewThreadSelector:] and -performSelectorInBackground

I've been using -performSelectorInBackground in many of my apps, sort of oblivious to -detachNewThreadSelector. Now I am wondering what the differences are between the two. Are they pretty much interchangeable, or are there differences and places where one is superior to the other? Thanks!
They're identical. See documentation.
performSelectorInBackground:withObject:
The effect of calling this method is the same as if you called the detachNewThreadSelector:toTarget:withObject: method of NSThread with the current object, selector, and parameter object as parameters.
As Michael says, they are identical. I think, to use a thread by performSelectorInBackground:withObject: is easier way rather than NSThread.
However, NSThread can control its priority, stacksize, etc. If you'd like to customize the behavior, I recommend NSThread instead of performSelectorInBackground:withObject:.
Corey, if you're running on a new thread and you're using [object autorelease], you'll need to create your own autorelease pool. Fairly simple to do:
- (void)uploadDataOnThread
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// do something here...
[pool release];
}
Interesting you guys can't point out any differences between them-
I'll tell you this much. We have an iphone app that was locking up while we displayed the "internet activity" disclosure icon in the top bar and a window that said "Sending..." while we sent an audio file up to a server and performSelectorInBackground: was NOT working. When we swapped out performSelectorInBackground with detachNewThreadSelector, it worked fine but now it complains that no autoreleased objects running in that thread are subject to being released by the pool.. maybe this is because the pool is in the main thread?