我已经阅读了我能找到的所有相关问题,但我仍然卡住了,所以我希望有人会发现我的推理错误。
我正在尝试定期更新一些UIView。为简单起见,我将代码缩减为以下内容。简介:在viewDidLoad中,我在新的后台线程上调用方法。该方法在主线程上调用一个方法,该方法应该更新一些UILabel。代码似乎工作正常:后台线程不是主线程,调用UILabel更新的方法在主线程上。在代码中:
在viewDidLoad中:
[self performSelectorInBackground:@selector(updateMeters) withObject:self];
这会创建一个新的后台线程。我的方法updateMeters(为简单起见)现在看起来像这样:
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;
}
最后,updateUI就是这样做的:
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
据我所知,这应该有效。但不幸的是,它没有......注释掉的dispatch_async()
产生了相同的结果。
答案 0 :(得分:1)
很可能你的格式声明错了。
label.text = [NSString stringWithFormat:@"%f", someTimeDependentValue];
确保someTimeDependentValue是一个浮点数。如果它是一个int,它可能会被格式化为0.0000。
Here's a repo显示您所描述的工作版本。任何错误都与线程无关。
答案 1 :(得分:0)
为了扩展我的评论,这里是使用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 = ...;
}
我在项目中广泛使用了一种更精细的方法。这就是引擎的概念。
我会使用计时器在后台运行引擎。在关键时刻,它会使用NSNotificationCenter
/ dispatch_async
在主线程上使用dispatch_get_main_thread()
发布通知,然后您的任何一个视图都可以通过更新其UI来订阅和处理该通知。