2012-06-20 31 views
16

我知道UIView不是线程安全的,所以我不能添加一个背景线程的视图,解决这个问题可以在后台线程上创建一个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]; 
} 

预先感谢。

+0

我相信你是对的。在后台创建它,但更新主要的UI。 –

回答

15

UIView

线程注意事项

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

initWithFrame:的调用明确地不是线程安全的。致电setText:可能不是线程安全的,属于“操纵”条款。这些肯定不是线程安全的。

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

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

+5

对不起,但你能澄清你的答案?苹果特别提到,在后台创建视图是可以的,但你说的不是。为什么? –

+0

@iamataptool可能你可以用'init'方法安全地创建UIView,但不能用'initWithFrame:'方法? – DanSkeel

+0

CALayer提示使我的一天和一周。非常感谢! –

0

Drawing and Printing Guide状态:

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

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

+0

在我的情况下,我的应用程序通过'UIApplicationLaunchOptionsLocalNotificationKey'唤醒,所以它在后台。是否可以,如果我在应用程序在后台时执行子视图添加? https://stackoverflow.com/questions/46584566/how-to-stop-handle-ui-operations-in-ios-when-app-moves-to-background-state – Nil

3

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

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

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

显示如下图所示:

enter image description here

相关问题