This post is a free translation of the Xcode article : A Better Way to Storyboards by Stan Ostrovskiy
Some code examples in the original article are outdated (due to the release of Swift 3) and have been changed in translation.
Tips and tricks for working with Interface Builder.
Apple has seriously improved Interface Builder in the new Xcode 8. Using size classes has become more intuitive, the ability to scale a storyboard is very convenient, and the full preview right in Interface Builder is just awesome. For those who have had doubts about using Interface Builder, this can be a good plus.
On the other hand, many developers still have some problems with Interface Builder when they create large multi-screen applications with complex navigation.
In this article I will share some of the best practices for working with storyboards in your project. Are you already using Interface Builder, or are you just taking the first steps in this direction? - in any case, these tips will be useful for you.
Is there a single main.storyboard file in your project that looks like this?
From the point of view of the designer, everything is good: you can see the UI and navigation completely. And this is exactly what Interface Builder was created for.
But for the developer, this has many problems:
How to connect different storyboards in your project? There are two ways.
Use storyboard referencing links that appeared in Xcode 7.
You can read more about the first method here .
I will talk about the second method, as it is widely used for complex projects.
This will simplify the rules of naming, as well as give some "buns" about which we will talk in paragraph 3.
When it comes to initializing a view controller through a storyboard, I often see the following code:
let storyboard = UIStoryboard(name: “Main”, bundle: nil) let homeViewController = storyboard.instantiateViewController(withIdentifier: “HomeViewController”)
A bit "dirty": you need to name a storyboard, you need a viewboard ID view controller, and you need to use this pattern every time you create a HomeViewController.
It is better to transfer this code to the controller class itself and use the static method to initialize the controller using a storyboard:
class HomeViewController: UIViewController { static func storyboardInstance() -> HomeViewController? { let storyboard = UIStoryboard(name: “HomeViewController”, bundle: nil) return storyboard.instantiateInitialViewController() as? HomeViewController } }
If you follow the previous tip (the same file names), you can avoid the "story" name of the storyboard and use String (describing :) :
let storyboard = UIStoryboard(name: String(describing: self), bundle: nil)
Make sure that the storyboard file has the same name as the controller class. Otherwise, your application will “crash” when you try to create a link to such a storyboard.
This makes your code more readable and fault tolerant:
class HomeViewController: UIViewController { static func storyboardInstance() -> HomeViewController? { let storyboard = UIStoryboard(name: String(describing: self), bundle: nil) return storyboard.instantiateInitialViewController() as? HomeViewController } }
If you want to access the view controller via instantiateInitialViewController (), make sure you specify this view controller as the initialViewController in Interface Builder. If you have multiple view controllers on the same storyboard, you will need to use instantiateViewController (withIdentifier: _)
Now, initializing such a controller view will take one line:
let homeViewController = HomeViewController.storyboardInstance()
Simple and straightforward, isn't it?
You can use the same approach to initialize a nib view:
class LoginView: UIView { static func nibInstance() -> LoginView? { let nib = Bundle.main.loadNibNamed(String(describing: self), owner: nil, options: nil) return nib?.first as? LoginView } }
You will not have transitions if you follow the advice from point 1. But even if you have several view controllers in one storyboard, using transitions (segues) to navigate between them is not a good idea:
What is the alternative? When you want to go to the next controller view by pressing the button, simply add an IBAction for this button and initialize the controller view in the code: this is just one line, as you remember from step 3.
@IBAction func didTapHomeButton(_ sender: AnyObject) { if let nextViewController = NextViewController.storyboardInstance() { // initialize all your class properties // nextViewController.property1 = … // nextViewController.property2 = … // either push or present the nextViewController, // depending on your navigation structure // present(nextViewController, animated: true, completion: nil) // or push navigationController?.pushViewController(nextViewController, animated: true) } }
Sometimes navigation involves returning the user to the previous screen.
A very common mistake: use the new transition to navigate to the previous view controller. Such a transition creates a new instance of the view controller, which is already in the stack, instead of removing the current view controller and thus returning to the previous one.
Starting with iOS 7, Interface Builder gives you the ability to "unwind" the navigation stack.
Unwind segue allows you to specify a return to the previous screen. It sounds pretty simple, but in practice it requires some additional actions and only confuses the developer:
What is a simpler way?
It's easier to do this in code: instead of creating an "unwind" action for your button, create a regular IBAction and use dismissViewController or popViewController (depending on your navigation):
@IBAction func didTapBackButton(_ sender: AnyObject) { // if you use navigation controller, just pop ViewController: if let nvc = navigationController { nvc.popViewController(animated: true) } else { // otherwise, dismiss it dismiss(animated: true, completion: nil) } }
That's all for today. I hope you find something useful for yourself.
Thanks to the method described in this article, I greatly simplified working with storyboards in my current project. While I was working on it alone, everything was fine, but as soon as other developers appeared, working with a storyboard turned into a real hell. Out of despair, we practically switched to the "banana method" (you can read here in the section "Pass the banana").
Of course, ideally, you will need to come to VIPER sooner or later. But this will be another post.
Source: https://habr.com/ru/post/312766/
All Articles