Most good applications have more than a single screen. I bet that most app ideas you have in your head involve at least a couple of different screens. Maybe you would like to display a table view or a collection view that links to a detail page. Or perhaps you want your user to drill down into your app's contents in a different way. Maybe you don't have detail views, but you would like to display a couple of modal screens for data input instead.
Every time your user moves from one screen in your app to another, they are navigating. Navigation is an essential aspect of building an app, and it's vital that you understand the possibilities and patterns for building good navigation on the iOS platform. The easiest way to gain insight into navigation is by using a storyboard to explore the available options.
Up until now, you have used your storyboard to create the layout for a single screen. However, the name storyboard implies that you can do a lot more than laying out a single screen. The purpose of using a storyboard is the ability to lay out all screens of your application in a single place so you can easily see how screens and sections of your app are related and how users navigate between them. In this section, you will add a second view controller to your storyboard that functions as a detail page when a user taps on a contact.
Open the Main.storyboard file and drag out a view controller from the Object Library by clicking the round icon with a square in the middle in the top bar of Interface Builder. Drop it next to the existing view controller. Next, look for a label in the Object Library and add it to the new view controller you just added to the storyboard.
Place the label in the center of the view and add some text to it so you can easily recognize it as your second view controller later. Then, add two constraints to center the label in its parent view. Do this by clicking the Align button in Interface Builder's bottom-right corner and selecting the Horizontal center and Vertical center constraints.
Before you add all the content for the contact detail page to the second view controller, it's a good idea to configure the navigation from the overview page to the detail page. To do this, you're going to create a selection segue. A segue is a transition from one screen to the next. Not all segues are animated; sometimes you might need to present the next screen without performing a beautiful animation. Both animated and static transitions can be set up with segues.
Any time you connect one screen to the next to perform navigation, you are creating a segue. Some segues are performed when the user taps a button; these are called action segues. Segues that are only triggered through code are called manual segues. The selection segue you're going to use in this sample is a segue that is set up by connecting a table view cell or collection view cell to a next screen. The segue is performed when the user taps on a cell.
To set up your selection segue, select the prototype collection view cell you have created for the contacts overview page. Next, press and hold the Ctrl key while you drag from the cell to the second view controller. When you release the mouse over the second view controller, a list of options is shown. This list of possibilities describes how the detail view will be presented to the user. For instance, you can choose a modal presentation style. This will display the detail page with an upward animation from the bottom of the screen. Not quite the kind of animation you're looking for in this instance but interesting to explore either way.
A better way to show the contact is by adding it to the navigation stack. Doing this will make a back button appear in the navigation bar, and the user will immediately understand that they are looking at a detail page due to the animation that moves the new view controller in from the right-hand side of the screen. To set this up, you need to select the show segue. This segue pushes the newly presented view controller onto the existing navigation controller's navigation stack. Go ahead and run your app; you can navigate back and forth between the overview and the detail page.
In the previous chapter, you implemented a nice bounce animation when a user taps the cell. Unfortunately, the transition to the detail page takes place before the animation has a chance to execute. So even though the show segue works precisely as needed, it's better to use a manual segue in this case. This allows you to perform the animation and trigger the segue manually once the animation is finished.
Go back to the storyboard and click on the line that connects the collection view cell to the view controller. Press Backspace to delete the segue. Drag from the yellow circle at the top of the first view controller window to the second view controller. This is how you create a manual segue. When the dialog to determine how the segue is performed appears, select show again because you don't want to use a different animation. Click on the connecting line to inspect the segue and set the value for the Identifier field to detailViewSegue in the Attributes Inspector. Similar to how you set a reuse identifier on table view cells and collection view cells, segues also use a string as their identifier.
To trigger the segue after the animation, you must manually do so from your code. Open ViewController.swift and update the implementation of collectionView(_:didSelectItemAt:) as shown in the following snippet. Pay special attention to the last completion closure because that's where the segue is performed:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let cell = collectionView.cellForItem(at: indexPath) as? ContactCollectionViewCell else { return } UIView.animate(withDuration: 0.1, delay: 0, options: [UIView.AnimationOptions.curveEaseOut], animations: { cell.contactImage.transform = CGAffineTransform(scaleX: 0.9, y: 0.9) }, completion: { _ in UIView.animate(withDuration: 0.1, delay: 0, options: [UIView.AnimationOptions.curveEaseIn], animations: { cell.contactImage.transform = .identity }, completion: { [weak self] _ in self?.performSegue(withIdentifier: "detailViewSegue", sender: self) }) }) }
This change makes sure the animation is finished before moving to the detail page. Build and run your app on any device to see your manual segue in action. The next step is to learn a bit more about layouts that react to changes in their environment by setting up the contact detail page.