UILabel文本内容未被更新

39

我无法更改UILabel的文本。在viewDidLoad中,UILabel的代码如下:

startLabel=[[UILabel alloc] initWithFrame:CGRectMake(75, 395, 200, 30)];
startLabel.text=@"Recording Sound ...";
startLabel.backgroundColor=[UIColor clearColor];
startLabel.textColor=[UIColor whiteColor];
startLabel.font=[UIFont boldSystemFontOfSize:17];

[self.view addSubview:startLabel];

后来,如果我想用以下代码更改文本的标签,它不会在应用程序上更改:

startLabel.text=@"Searching Database ...";
或者
[startLabel setText:@"Searching Database ..."];

UILabel不是空的,在调试期间我打印了它,它显示为:

(gdb) po startLabel
<UILabel: 0x2c1a30; frame = (75 395; 200 30); text = 'Searching Database ...'; 
clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x2ae8f0>>

所以,UILabel中的标签文本改变了,但屏幕上没有更新。

请问有人可以告诉我我错过了什么吗?谢谢。

编辑1:我尝试了performSelectorOnMainThread: - 对我没有用。

编辑2:我正在使用AVFoundationASIHTTP类来录制声音并在此处上传录制的文件。 没有使用任何线程。


你在哪里更新文本(使用什么方法)?它需要在同一个线程上进行(请参见:https://dev59.com/QVfUa4cB1Zd3GeqPFTDA)。 - Ben Jakuben
@Ben: 那不是给MonoTouch用的吗?而且,我在同一个线程内,只是另一个函数而已! - Ahsan
我完全没有意识到这是一个MonoTouch的问题,但我在Mac论坛上找到了一个类似的问题,需要使用performSelectorOnMainThread在同一线程上运行(http://forums.macrumors.com/showthread.php?t=463200),所以我只是想知道你是从哪里调用它的。 - Ben Jakuben
@Ben:不行啊.. :( 有其他建议吗? - Ahsan
5个回答

50

可能你遇到了线程问题,就像上面的评论提到的一样。如果你有一个在主线程上运行并执行某些活动(比如搜索数据库)的方法,对UI的更新将不会被提交,直到运行循环获得控制权。因此,如果你在主线程上有一个耗时长的任务正在进行,请在设置标签文本后运行此代码:

- (void)doSomethingTimeConsuming
    ... consume some time ...
    ... set text of label ...
    [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
    ... continue long operation ...
}

这应该可以清除你所做的任何UI更改。虽然这可能是一个明智和功能性的黑客,但并不比另一种选择好。我强烈建议您在后台线程上执行应用程序的耗时任务,并使用 performSelectorOnMainThread:withObject:waitUntilDone: 通过主线程更新UI。请参阅Apple关于iOS线程管理的页面。


谢谢您的建议。这是我在应用程序/视图中正在做的事情。我正在使用AVFoundation录制一些声音,并使用ASIHTTP类上传录制的声音。没有什么特别的......在上传文件的函数(自定义函数)中,我最初编写了更改标签的代码。但是没有任何作用。我甚至尝试了performSelectorOnMainThread...也没有用。您认为录制/上传是否符合单独的线程要求?请建议我该怎么做。谢谢。 - Ahsan
1
[NSRunLoop mainRunLoop].. 这个东西起作用了... 另一个替代方案没用... 非常感谢... :) 你让我的一天变得美好了! - Ahsan
1
谢谢,我遇到了类似的问题,但是performSelectorOnMainThread:withObject:waitUntilDone:解决方案对我非常有效。追溯问题发现,一个UI更新被触发(但没有显示),来自于一个设置在异步URL请求完成后运行的代码块。我甚至建议将该解决方案更突出地显示在您的答案中,以便人们不会错过它,因为它目前是被接受的答案? - Matt
即使是[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0]];(时间间隔为0),对我也有效。 - dollar2048

50
在我的情况下,更新的函数是从一个触摸识别器线程中调用的,但是当我改变标签文本属性值的地方,我将它放回到主线程中:
dispatch_async(dispatch_get_main_queue(), ^{
    [self.someLabel setText:someString];
});

简单易懂。谢谢! - ecnepsnai
我试图从通知中心调用的方法中刷新文本,这解决了问题,谢谢! - fray88

5

我有一个显示等级数字的UILabel,在UIViewController上无法更新到新的等级数字。我能找到的唯一可行的解决方案是在拥有该UILabel的视图控制器的主线程上调用setNeedsDisplay。

-(void)changeLevelLabel:(int)theLevel {
dispatch_async(dispatch_get_main_queue(), ^{
    self.levelLabel.text = [NSString stringWithFormat:@"%d",theLevel];
    [self.levelLabel setNeedsDisplay];
});

请参考http://iosdevelopmentjournal.com/blog/2013/01/16/forcing-things-to-run-on-the-main-thread/以获取更详细的解释。


3

我的答案有点出人意料,但是合理——只是没人会太认真考虑这个问题。

我需要在接收到我在其他地方触发的NSNotification时更新UILabel。然而,该通知是从后台线程触发的,因此即使更新标签文本的监听器方法也在后台线程中触发。

如果您依赖于NSNotification来更新标签或任何视图,请确保从主UI线程触发NSNotification


0
如果您正在使用localize-Swift cocoapod,如果您将localized key设置为,则在设置标签上的任何文本后,该值将被设置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接