7

Related: Is it ok to create a UIView on a background thread?

Is this background-thread code safe?

let viewController = MyViewController(nibName: nil, bundle: nil)
viewController.title = "My Title"
viewController.myProperty = true
dispatch_async(dispatch_get_main_queue(), {
    self.navigationController?.pushViewController(viewController, animated: true)
})
Community
  • 1
  • 1
ma11hew28
  • 121,420
  • 116
  • 450
  • 651
  • Thanks! :-) So then, `MyViewController(nibName: nil, bundle: nil)` doesn't trigger any UI updates? `viewController.myProperty = true` has no side effects. It's just a simple property. – ma11hew28 Nov 04 '15 at 00:02

2 Answers2

3

It seems that @ozgur answer is out of date now. If you try and create a UIViewController from a background thread in the latest version of Xcode (Version 11.5 at the time of writing) then you will get the following error:

-[UIViewController init] must be used from main thread only
pls
  • 1,522
  • 2
  • 21
  • 41
2

It depends on what the instance variables are actually doing. General rule is that the code running by a background thread should not trigger any UI updates such as view.addSubview(..) or view.setNeedsLayout etc, then it is safe to play around with a view controller using a background thread.

Another example would be navigation controllers. For instance, once a view controller was pushed onto a navigation stack, even updating viewController.title can be dangerous so you should make sure viewController.myProperty = true doesn't trigger any UI updates. Personally, I would do the following assignments in the main thread to feel safe:

dispatch_async(dispatch_get_main_queue(), {
  viewController.title = "My Title"
  viewController.myProperty = true
  ...
})

Long story short, you can initialize new UIView or UIViewController (or any UIResponder) in a background thread however, you should be changing any of its properties triggering UI updates within main thread. So create in background but update in main thread.

Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119
  • I believe that handling some properties on the main queue would not be enough to bypass the problems here. Alone pushing the view controller to the navigation stack is something what should be done on the main queue; while all the view controller lifecycle methods will get invoked (and also `layoutsubviews` etc stuff of the view controllers view object). All in all, it is not safe! – antonio Aug 31 '16 at 10:30
  • @antonio I think you have problem in understanding what you are reading. We are basically saying the same thing. It is perfectly safe to initialize a view controller within any thread but once UI updates comes into play, you must always do that on the main queue. Creating a view controller won't trigger any methods regarding its lifecycle like `viewDidLoad`, `viewWillAppear`, or `viewDidLayoutSubviews`. – Ozgur Vatansever Aug 31 '16 at 16:54
  • I am not talking about creating; I talk about pushing in the navigation stack. – antonio Sep 01 '16 at 13:42
  • pushing in the navigation stack is a UI update so must be handled in the main queue. – Ozgur Vatansever Sep 02 '16 at 04:43