【问题标题】:UILabel not beeing displaying instantly using threadUILabel 没有使用线程立即显示
【发布时间】:2013-03-05 16:40:44
【问题描述】:

我想在线程中加载一些视图以避免 UI 冻结等待加载结束。

我不习惯穿线,所以我做了一个快速测试。我的代码只是尝试在线程中创建视图并将此视图添加到主线程的当前视图控制器视图中。

我的 UIView 正在工作,但对于我的 UILabel,我必须等待 20 到 60 秒才能将其显示在屏幕上。

我使用 UIButton 进行测试,在这种情况下,按钮会立即显示,但按钮内的标签显示的延迟与我的 UILabel 相同。

让它按我想要的方式工作的唯一方法是添加一个 [lbl setNeedsDisplay];在主线程中强制 UILabel 立即显示。 为什么?没有这条线可以做吗?

    dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL);
dispatch_async(queue, ^{

    // NEW THREAD
    UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 48)];
    lbl.text = @"FOO";

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
    view.backgroundColor = [UIColor redColor];

    // MAIN THREAD
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.view addSubview:lbl];
        [lbl setNeedsDisplay]; // Needeed to see the UILabel. WHY???

        [self.view addSubview:view];
    });
});
dispatch_release(queue);

【问题讨论】:

  • 创建 UIView 不是关键任务,您不需要在另一个线程中进行。
  • 我正在尝试制作日历。在这个日历中,我在 6x7 的网格中每天有 42 个按钮,如果有活动,我必须在每天的下方有一个点。我将带有 CALayer 的点添加为日期按钮的子层,并且在月份之间的过渡期间显示此点有一些延迟。当我寻找这种延迟的原因时,它似乎来自 addSubLayer。所以我想在初始化时在后台添加这个子层,并使其隐藏或不隐藏在主线程中。如果您对此有一些想法,我正在倾听您的意见:-)
  • @zakhej 如果计划进行一些体面到繁重的数据处理,那就是。
  • 我建议向我们展示用于计算视图的代码。那就是你的延迟所在。添加子视图通常不会给你那种延迟。我做过类似的日历视图,没有遇到这个问题。
  • @sosborn 当我只评论这一行时 [self.layer addSublayer:layer];延迟消失。我保留创建子层的代码。所以我认为它来自这里。你怎么做你的点? CALayer、UIImageView...?

标签: ios objective-c uiview uilabel grand-central-dispatch


【解决方案1】:

你也应该在主队列上设置标签的文本:

dispatch_async( dispatch_get_main_queue(), ^{
    UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 48)]
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
    lbl.text = @"FOO";
    [self.view addSubview:lbl];
    [self.view addSubview:view];
});

最好将所有 UI 内容保留在主队列中。

更新

看来initWithFrame: 不是线程安全的(可在SO answer 上找到,另请参阅UIView 文档中的Threading Considerations)。

【讨论】:

  • 它不是这样工作的。我仍然必须使用 [lbl setNeedsDisplay];
  • 我们不能用返回键在 cmets 中创建新行?
  • 对不起我的第一个答案,它似乎有效。我不得不删除 lbl.text = @"FOO";也在线程中。我认为他检测到 UILabel 中相同文本的分配并且他不强制刷新。但我不明白为什么它不能与 uilable 一起使用,但它可以与 uiview 一起使用?
  • 谢谢迈克,但在你的更新中,我没有后台代码了。也许我错过了什么,因为我是一个线程新手。
  • @Alex 如果您所做的只是创建这样的视图,我认为您不会注意到留在主线程上会影响性能。一般规则是,如果它是 UI,它就在主线程上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-27
  • 1970-01-01
  • 1970-01-01
  • 2022-07-08
  • 2011-04-20
相关资源
最近更新 更多