在后台线程上创建视图,在主线程中添加主视图
问题描述:
我是新来的客观C,来自.NET和Java背景。在后台线程上创建视图,在主线程中添加主视图
所以我需要以异步方式创建一些UIWebViews中,我使用
dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL);
dispatch_async(queue, ^{
// create UIwebview, other things too
[self.view addSubview:webView];
});
你owuld想象这是我自己的队列这样做会引发错误:
bool _WebTryThreadLock(bool), 0xa1b8d70: Tried to obtain the web lock from a thread other
than the main thread or the web thread. This may be a result of calling to UIKit from a
secondary thread. Crashing now...
所以,我该怎么加主线程的子视图?
答
。我不会使用performSelectorOnMainThread:withObject:waitUntilDone:
,而是在主队列上执行子视图添加。
dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL);
dispatch_async(queue, ^{
// create UIwebview, other things too
// Perform on main thread/queue
dispatch_async(dispatch_get_main_queue(), ^{
[self.view addSubview:webView];
});
});
它是细实例化UIWebView
上的背景队列。但要将它作为子视图添加,您必须位于主线程/队列中。从UIView
文档:
线程注意事项
操作,以应用程序的用户界面必须在主线程上发生。因此,您应该始终从应用程序主线程中运行的代码中调用UIView类的方法。唯一不是严格需要的时候是创建视图对象本身,但所有其他操作应该在主线程上进行。
答
大多数UIKit对象,包括UIView
的实例,必须从主线程/队列操作只有。您无法将消息发送到任何其他线程或队列上的UIView
。这也意味着你不能在任何其他线程或队列上创建它们。
答
正如罗布说的用户界面的变化应该只在主thread.You完成试图既然你已经使用了调度队列从二级thread.Change添加代码[self.view addSubview:webView];
到
[self.view performSelectorOnMainThread:@selector(addSubview:) withObject:webView waitUntilDone:YES];
要小心,即使initWithFrame不保证是线程安全的。请参阅http://*.com/questions/11122957/is-it-ok-to-create-a-uiview-on-a-background-thread – stefreak 2015-02-12 17:53:33
也许我对'线程安全'的理解是错误的。但我认为线程安全意味着可以同时从多个线程操纵一个对象。例如。你可以考虑一个线程安全的数组,它可以让你从多个线程中添加对象。 然而,在这种情况下,我们没有操纵或访问来自多个线程视图对象/同时队列。我们在一个线程/队列上创建它,然后将其交给另一个线程/队列。 – Florian 2015-02-12 19:00:20
事实证明,我所链接的问题的答案是误导 - 抱歉。苹果表示:“唯一一次可能不是绝对必要的是创建视图对象本身,因此它应该是安全的。 – stefreak 2015-02-12 20:41:12