I have a UIViewController class with a variable shared that allows other classes to reach it as a singleton. However, the compiler (with Main Thread Checker enabled in Scheme Settings) is flagging the variable in purple with the warning:
-[UIViewController init] must be used from main thread only
I was not aware that merely including a shared variable to initiate the View Controller as a singleton is not allowed. I guess it makes sense insofar as when you initiate the VC it initiates the life cycle and views. But would appreciate someone confirming this and/or further shedding light on what is going on.
Here is the code that triggers the warning:
@objcMembers class MyVC : UIViewController, UITableViewDelegate, UITableViewDataSource,UITextViewDelegate {
static var shared = MyVC()
}
I have a UIViewController class with a variable shared that allows other classes to reach it as a singleton. However, the compiler (with Main Thread Checker enabled in Scheme Settings) is flagging the variable in purple with the warning:
-[UIViewController init] must be used from main thread only
I was not aware that merely including a shared variable to initiate the View Controller as a singleton is not allowed. I guess it makes sense insofar as when you initiate the VC it initiates the life cycle and views. But would appreciate someone confirming this and/or further shedding light on what is going on.
Here is the code that triggers the warning:
@objcMembers class MyVC : UIViewController, UITableViewDelegate, UITableViewDataSource,UITextViewDelegate {
static var shared = MyVC()
}
Share
Improve this question
asked 17 hours ago
user6631314user6631314
1,9661 gold badge18 silver badges55 bronze badges
6
|
Show 1 more comment
2 Answers
Reset to default 0Your question is making the assumption that you are getting a compiler warning due to the use of a singleton view controller. This is not the case.
The warning about calling UIViewController init
on a non-main queue is actually a runtime warning. Note that the scheme setting "Main Thread Checker" is under the "Runtime API Checking" section of the Diagnostics tab. Note that compiler warning show in Xcode as yellow triangles. Runtime warnings, such as this, appear as purple triangles.
The warning is not due to the code you posted. It is due to some other code that is making the first call to MyVC.shared
from a non-main queue. The solution is to find the offending code and ensure, like all UI code, that it is only called from the main queue.
Put a breakpoint on the line static var shared = MyVC()
and run your app to see which code calls it first. You should see from the stack trace shown at that point that it is on something other than Thread 0.
A view controller can't be a singleton, that is meaningless.
You simply do this
class ChartView: UIViewController {
static var current: ChartView?
set it to self in viewDidLoad
Access it from elsewhere as ChartView.current?
.
if your app is broken and you accidentally make two or more of the ChartView
screens (which can happen) it's just your fault, don't do that.
That is generally poor practice, but that's how you do what you're trying to do.
(Generally you never do this - other than for the baseboard of the app, which is how 99% of apps work.)
UIViewController
singleton is definitely not a pattern I would be following. While a "root" view controller may indeed be in the view controller hierarchy for the lifetime of your app, it is still probably better to obtain the reference dynamically via, say, therootViewController
property of your window or scene, than to use a singleton. Your question also implies that you are using a view controller where a data model would be more appropriate. – Paulw11 Commented 16 hours agoMyVC.shared
is occurring from a non-main queue context. Since any operation that actually resulted in the view controller being added to the view hierarchy would have to be on the main queue, this would also indicate thatMyVC.shared
is not actually in the view hierarchy. You should be using one of the designated initialisers for aUIViewController
, notinit()
– Paulw11 Commented 16 hours agoWindow
, but now you should access the current window scene. Singletons make testing harder and lead to undesirable class coupling. I say that they can be useful and, yes, in some cases I will still use them, but I try not to. And a singletonUIViewController
is definitely a bad idea. – Paulw11 Commented 16 hours ago