In this blog, I am discussing how we can reduce a bunch of repetition code.
In old code structure, we use different storyboard and each storyboard contains multiple view controllers. So moving from one controller to another firstly we have to create an instance of storyboards and create the reference of view controller from that we can push or present view controller over the current view controller and that same code we have to write in each class where we are moving from one controller to the another. Here is the example of repetition which we usually used to write:-
1 2 3 |
let str = UIStoryboard(name: "Main", bundle: nil) let vc = str.instantiateViewController(withIdentifier: "ViewController") as! ViewController self.navigationController?.pushViewController(vc, animated: true) |
As we all know in swift, we say enum class first last so with the use enum we create a number of case equal to the number of storyboards our project contains with their raw value(which refers their actual name):-
1 2 3 4 5 6 |
enum AppStoryboard: String { case main = "Main" case main1 = "Main1" case main2 = "Main2" case main3 = "Main3" } |
For moving one controller we need these things one is storyboard instance and another is view controller reference. From storyboard raw value we can get storyboard instance and from View controller itself, we can get view controller’s identifier from them we can create there reference. so we can use generics to implement this feature in the enum:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
enum AppStoryboard: String { case main = "Main" case main1 = "Main1" case main2 = "Main2" case main3 = "Main3" var instance: UIStoryboard { return UIStoryboard(name: self.rawValue, bundle: Bundle.main) } func viewController<T: UIViewController>(viewControllerClass: T.Type) -> T { let storyboardID = (viewControllerClass as UIViewController.Type).storyboardID guard let scene = instance.instantiateViewController(withIdentifier: storyboardID) as? T else { fatalError("ViewController with identifier \(storyboardID), not found in \(self.rawValue) Storyboard.\nFile : \(file) \nLine Number : \(line) \nFunction : \(function)") } return scene } func initialViewController() -> UIViewController? { return instance.instantiateInitialViewController() } } extension UIViewController { // Not using static as it wont be possible to override to provide custom storyboardID then class var storyboardID: String { return "\(self)" } static func instantiate(fromAppStoryboard appStoryboard: AppStoryboard) -> Self { return appStoryboard.viewController(viewControllerClass: self) } } |
How to use them:-
1 2 |
let vc = ViewController.instantiate(fromAppStoryboard: .main) self.navigationController?.pushViewController(vc, animated: true) |
I hope from this, it will make you more comfortable dealing with different storyboards and view controllers. Thanks for tuning in once again!
Be the first to comment.