可以在后台线程上创建UIView吗?

时间:2012-06-20 15:30:00

标签: objective-c ios uiview uiviewcontroller nsthread

我知道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];
}

提前致谢。

3 个答案:

答案 0 :(得分:18)

来自UIView

  

线程注意事项

     

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

initWithFrame:的调用显然不是线程安全的。对setText:的调用可能不是线程安全的,属于“操纵”条款。这些肯定不是线程安全的。

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

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

答案 1 :(得分:5)

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

  

[UView init]必须仅从主线程调用

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

显示以下图片:

enter image description here

答案 2 :(得分:-1)

Drawing and Printing Guide州:

  

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

因此,据我所知,似乎唯一的问题与“绘图相关的操作”有关。如果我们假设一个正确的类只在它的drawRect:方法中执行这样的操作,那么你建议的方法应该没问题。