Is it OK to create a UIViewController on a background thread?
Asked Answered
G

2

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)
})
Gassing answered 3/11, 2015 at 23:37 Comment(1)
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.Gassing
C
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.

Corotto answered 22/12, 2015 at 19:31 Comment(4)
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!Mercy
@Mercy 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.Corotto
I am not talking about creating; I talk about pushing in the navigation stack.Mercy
pushing in the navigation stack is a UI update so must be handled in the main queue.Corotto
P
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
Plurality answered 19/6, 2020 at 21:32 Comment(0)
C
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.

Corotto answered 22/12, 2015 at 19:31 Comment(4)
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!Mercy
@Mercy 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.Corotto
I am not talking about creating; I talk about pushing in the navigation stack.Mercy
pushing in the navigation stack is a UI update so must be handled in the main queue.Corotto

© 2022 - 2024 — McMap. All rights reserved.