I've read all related questions I could find but I'm still stuck, so I hope someone will spot my reasoning error.
I'm trying to periodically update some UIView. For simplicity, I've reduced the code to what's below. Summary: In viewDidLoad, I call a method on a new background thread. That method calls a method on the main thread which is supposed to update some UILabel. The code seems to work correctly: the background thread is not the main thread and the method calling the UILabel update is on the main thread. In code:
In viewDidLoad:
[self performSelectorInBackground:@selector(updateMeters) withObject:self];
This creates a new background thread. My method updateMeters (for simplicity) now looks like this:
if ([NSThread isMainThread]) { //this evaluates to FALSE, as it's supposed to
NSLog(@"Running on main, that's wrong!");
}
while (i < 10) {
[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
//The code below yields the same result
// dispatch_async(dispatch_get_main_queue(), ^{
// [self updateUI];
// });
[NSThread sleepForTimeInterval: 1.05];
++i;
}
Finally, updateUI does just that:
if ([NSThread isMainThread]) { //Evaluates to TRUE; it's indeed on the main thread!
NSLog(@"main thread!");
} else {
NSLog(@"not main thread!");
}
NSLog(@"%f", someTimeDependentValue); //logs the value I want to update to the screen
label.text = [NSString stringWithFormat:@"%f", someTimeDependentValue]; //does not update
For all I know, this should work. But it doesn't, unfortunately... The commented out dispatch_async()
yields the same result.
Most likely you have your format statement wrong.
label.text = [NSString stringWithFormat:@"%f", someTimeDependentValue];
Make sure that someTimeDependentValue is a float. If it is an int it will likely get formatted to 0.0000.
Here's a repo showing a working version of what you describe. Whatever is wrong is not related to the threading.
To expand on my comment, here's a scenario that might be best achieved using a NSTimer:
-(void)viewDidLoad
{
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:<number of seconds per tick> target:self selector:@selector(timerTick:) userInfo:nil repeats:YES];
}
-(void)timerTick:(id)sender
{
label.text = ...;
}
There is a more elaborate approach which I use extensively in my projects. And that is the concept of an engine.
I would have an engine that runs in the background using a timer. And at key moments, it would post a notification using NSNotificationCenter
on the main thread using dispatch_async
/ dispatch_get_main_thread()
and any one of your views can then subscribe and handle that notification by updating their UI.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.