NSThread and updating objects in subviews
In my app I want to make un update of my database when I press a button. Because it takes some time for this job and not to freeze the hole app I decided to use NSThread.
This process can be started from different views, so I have placed the update code in my App Delegate. When pressing the update method I have this code:
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[NSThread detachNewThreadSelector:@selector(startTheBackgroundJob) toTarget:delegate withObject:nil];
In my delegate:
- (void)startTheBackgroundJob {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init开发者_如何学C];
//do some stuff here
self.percentageCompleted = (i * 100) / totalChars;
[[NSNotificationCenter defaultCenter] postNotificationName:@"refreshObjectsForUpdate" object:self];
//some other stuff
[pool release];
Basically inside my thread I want to update different progressViews with current progress. So I used NSNotificationCenter to send a message after each step of my thread.
In a viewController I am catching this message and I am doing:
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
double prc = delegate.percentageCompleted;
UILabel *l = (UILabel *)[self.view viewWithTag:444];
l.text = [NSString stringWithFormat:@"%f", prc];
But it refreshes my label only at the end of the thread.
What is the problem here? Can I used another approach for this?
Thanks.
From Apple's documentation:
In a multithreaded application, notifications are always delivered in the thread in which the notification was posted...
so you'll need to perform your code to update the UI explicitly on the main thread (with performSelectorOnMainThread:withObject:waitUntilDone:
or whatever is suitable).
@paulbailey is correct about performing the selector on the main thread. I would also add that, if what you're doing is high-performance, I would avoid using the notification center altogether. It's going to broadcast synchronously, which means every UI element will be updated every loop iteration. You can use the "waitUntilDone" flag on the performSelector method to make it asynchronous, but you may cause a lot of thread and context switches.
Take a look at NSNotificationQueue and coalesce masks. You can post as often as you like that way, and it will just coalesce the notifications until it's convenient to deliver them. This of course has lower delivery guarantees, so you'll want to check that it doesn't cause your UI to lag unacceptably.
精彩评论