If you look at the Apple docs, they say:
wait
A Boolean that specifies whether the current thread blocks until after the specified selector is performed on the receiver on the
main thread. Specify YES to block this thread; otherwise, specify NO
to have this method return immediately. If the current thread is also
the main thread, and you specify YES for this parameter, the message
is delivered and processed immediately.
So, if you call this method from the main thread, then it will be executed immediately.
But, there's really no point in doing so. If you are on the main thread, and wish to execute getBooks
on the main thread, then just do this:
-(void) viewDidLoad {
[super viewDidLoad];
[self getBooks];
}
If you show us what you're actually doing inside getBooks
, we might be able to help more. For example, if getBooks
is making a remote HTTP request, to get online book data, then you don't want to use performSelectorOnMainThread:
at all. You want to run that on a background thread, and then only call back the main thread to update your UI, once the network request has completed.
Update:
There's many ways to retrieve web content. If you are going to use the NSURLRequest
directly, as you are, then you should make sure this class implements the NSURLConnectionDelegate
protocol:
@interface MyViewController: UIViewController<NSURLConnectionDelegate> {
and then implement its methods per the Apple example
- (void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response
{
// this method is called when the server has determined that it
// has enough information to create the NSURLResponse
// it can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
[receivedData setLength:0];
}
- (void) connection:(NSURLConnection *) connection didReceiveData:(NSData *)data
{
// append the new data to the receivedData
[receivedData appendData:data];
}
- (void) connection:(NSURLConnection *) connection didFailWithError:(NSError *) error
{
// release the connection, and the data object
[connection release];
[receivedData release];
// inform the user
UIAlertView* netAlert = [[UIAlertView alloc] initWithTitle:@"" message:@"Oops!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[netAlert show];
[netAlert release];
}
- (void) connectionDidFinishLoading:(NSURLConnection *) connection
{
if ([receivedData length] > 0) {
// do something with the data, and then tell the UI to update
[self performSelectorOnMainThread: @selector(updateUI) withObject: nil waitUntilDone: NO];
}
// release the connection, and the data object
[connection release];
[receivedData release];
receivedData = nil;
}
-(void) updateUI {
[tableView reloadData];
someLabel.text = @"New Status";
// whatever else needs updating
}
A note: the code above was written before ARC was introduced. If your project uses ARC, you'll need to remove all those lines with release
calls. It is advisable, however, to make sure your receivedData
is properly retained, since you'll be using it across multiple calls.
Another note: NSURLConnection
can be used in multiple ways. It can be used synchronously, or asynchronously. And, you can always decide which thread to start it on. If you keep this:
-(void) viewDidLoad {
[super viewDidLoad];
[self getBooks];
}
then the connection will be started on the main thread. But, it will still be an asynchronous operation. In other words, it won't block viewDidLoad
until the network request finishes. However, if the user is going to be doing anything significant with the UI while the download happens (like scrolling), then you may find your UI becomes less responsive. If that's the case, you may either want to do this, or force the network operation onto a background thread. To do that, start it with:
-(void) viewDidLoad {
[super viewDidLoad];
[self performSelectorInBackground: @selector(getBooksInBackground) withObject: nil];
}
Then, the only problem with my above NSURLConnectionDelegate
code is that the background thread will not live long enough to deliver the response via your delegate callbacks. To keep it alive,
-(void) getBooksInBackground {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[self getBooks];
CFRunLoopRun(); // Avoid thread exiting
[pool release];
}
And then you must add this call to the end of both connectionDidFinishLoading
and connection:didFailWithError
to clean up this background run loop:
CFRunLoopStop(CFRunLoopGetCurrent());
Again, old code, so use
@autoreleasepool {
}
for ARC.