I know how to create singleton class in swift. The best and easy way to create singleton class is the following:
class Singleton {
static let sharedInstance = Singleton()
}
But I don't need singleton for any normal class. I need to create singleton for a viewcontroller class. So I'm using this code create singleton
class AViewController:UIViewController {
static let sharedInstance = AViewController()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
it gives me error near AViewController()
Missing argument for parameter 'coder' in call
Looks like it want me to initialize with init(coder: NSCoder)
. But what parameter or value should I pass through the coder
?
If you really wanted to have singleton for a view controller corresponding to some scene, you'd probably do something like:
class SecondViewController: UIViewController {
static let shared = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Foo")
}
In this example, the storyboard was Main.storyboard
and the storyboard identifier for the scene in question was Foo
. Obviously, replace those values for whatever was appropriate in your case.
Then your other view controller that was invoking this could do something like:
@IBAction func didTapButton(_ sender: Any) {
let controller = SecondViewController.shared
show(controller, sender: self)
}
I wouldn't recommend singletons for view controllers. View controllers (and their views) should be created when needed and be allowed to be deallocated when they're dismissed. And you're losing many storyboard benefits (by which you see the logical flow between scenes with segues between them). And, if you use this view controller in different contexts, you're inviting problems stemming from the view controller hierarchy falling out of sync with the view hierarchy. I really would discourage you from using singletons for view controllers.
But if you were going to do it, you could do something like that...
Try to do:
AppDelegate:
Add a reference to the ViewController, so you can access it globally, like so:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
private var viewController: ViewController?
func getViewController() -> ViewController {
if viewController == nil {
// make sure that the name of the storyboard is "Main"
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// make sure that you named the viewcontroller in storyboard (Storyboard ID), it is the identifier
viewController = storyboard.instantiateViewController(withIdentifier: "ViewControllerStoryboardID") as! ViewController
}
return viewController!
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// ....
}
AnotherViewController (Usage):
Now you can access it via "AppDelegate", like so:
class AnotherViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let vc = appDelegate.getViewController()
}
// ...
}
Hope this helped.