19

我知道 UIView 不是线程安全的,所以我不能在后台线程上添加视图,要解决这个问题,可以在后台线程上创建 UIView 然后将其添加到主线程上吗?

注意:我不在主线程上这样做的原因是因为我的实际代码要复杂得多,因此需要一段时间来创建所有视图并填充值。当我这样做时,我不希望 UI 变得无响应,所以我试图解决这个问题。

例如..

-(void)addLabel//called on background thread
{
    UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(0,0,40,100)];
    [label setText:@"example"]
    [self.view performSelector:@selector(addSubview:) onThread:[NSThread mainThread] withObject:example waitUntilDone:YES];
}

提前致谢。

4

3 回答 3

19

UIView

线程注意事项

对应用程序用户界面的操作必须在主线程上进行。因此,您应该始终从应用程序主线程中运行的代码调用 UIView 类的方法。唯一可能不是绝对必要的情况是在创建视图对象本身时,但所有其他操作都应在主线程上进行。

调用initWithFrame:明确地不是线程安全的。调用setText:可能不是线程安全的,属于“操作”条款。这些当然不承诺是线程安全的。

做你的工作来找出后台线程上的数据。然后在主线程上创建您的视图。如果有大量视图,您可以尝试使用dispatch_async()对主队列的多个调用来拆分工作。这可能会让 UI 保持响应;我没有对它进行过广泛的实验。

您可能还需要考虑尽可能切换UIViewCALayer。大多数CALayer工作可以在后台线程上完成。如果您有大量的视图,那可能无论如何都是低效的。如果只是计算视图数据需要很长时间,则表明您没有正确分离模型和视图信息。模型类应该独立于创建视图计算所需的一切。

于 2012-06-20T15:42:13.063 回答
7

我使用 Xcode 9.0 beta 3 (9M174d),收到警告。

[UView init] 只能从主线程调用

所以我认为你应该更好地在主线程中创建 UI

显示下图:

在此处输入图像描述

于 2017-08-02T11:35:09.353 回答
-1

绘图和印刷指南指出:

重要 UIKit 类通常不是线程安全的。所有与绘图相关的操作都应在应用程序的主线程上执行。

因此,据我了解,似乎唯一的问题与“绘图相关操作”有关。如果我们假设正确的类仅在其drawRect:方法中执行此类操作,那么您建议的方法应该没问题。

于 2012-06-20T15:37:36.933 回答