在后台线程上创建视图,在主线程中添加主视图

问题描述:

我是新来的客观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类的方法。唯一不是严格需要的时候是创建视图对象本身,但所有其他操作应该在主线程上进行。

+0

要小心,即使initWithFrame不保证是线程安全的。请参阅http://*.com/questions/11122957/is-it-ok-to-create-a-uiview-on-a-background-thread – stefreak 2015-02-12 17:53:33

+0

也许我对'线程安全'的理解是错误的。但我认为线程安全意味着可以同时从多个线程操纵一个对象。例如。你可以考虑一个线程安全的数组,它可以让你从多个线程中添加对象。 然而,在这种情况下,我们没有操纵或访问来自多个线程视图对象/同时队列。我们在一个线程/队列上创建它,然后将其交给另一个线程/队列。 – Florian 2015-02-12 19:00:20

+0

事实证明,我所链接的问题的答案是误导 - 抱歉。苹果表示:“唯一一次可能不是绝对必要的是创建视图对象本身,因此它应该是安全的。 – stefreak 2015-02-12 20:41:12

大多数UIKit对象,包括UIView的实例,必须从主线程/队列操作只有。您无法将消息发送到任何其他线程或队列上的UIView。这也意味着你不能在任何其他线程或队列上创建它们。

+5

这不完全正确。在后台实例化视图是完全正确的。从UIView文档:操作到应用程序的用户界面必须在主线程上进行。因此,您应该始终从应用程序主线程中运行的代码中调用UIView类的方法。唯一不是严格需要的时候是创建视图对象本身,但所有其他操作应该在主线程上进行。 – Florian 2013-02-24 07:48:08

+0

@Florian如果两个视图都不与UI交互,在后台使用方法addSubview是否正确? – 2017-06-12 12:22:11

+0

@BohdanSavych我不确定。你的用例是什么? – Florian 2017-06-16 06:40:33

正如罗布说的用户界面的变化应该只在主thread.You完成试图既然你已经使用了调度队列从二级thread.Change添加代码[self.view addSubview:webView];

[self.view performSelectorOnMainThread:@selector(addSubview:) withObject:webView waitUntilDone:YES];