Difference between revisions of "Implementing iOS 8 TableView Navigation using Storyboards in Xcode 6 and Swift"

From Techotopia
Jump to: navigation, search
Line 23: Line 23:
  
  
[[File:]]
+
[[File:ios_11_table_view_attraction_view_controller.png]]
 
   
 
   
 
Figure 30-1
 
Figure 30-1
Line 35: Line 35:
 
   
 
   
  
[[File:]]
+
[[File:ios_11_table_view_navigation_controller_segues.png]]
  
 
Figure 30-2
 
Figure 30-2
Line 46: Line 46:
  
  
[[File:]]
+
[[File:ios_11_table_view_navigation_controller_segues.png]]
 
   
 
   
 
Figure 30-3
 
Figure 30-3
Line 74: Line 74:
 
   
 
   
  
[[File:]]
+
[[File:ios_11_table_view_web_kit_view.png]]
  
 
Figure 30-4
 
Figure 30-4
Line 122: Line 122:
 
   
 
   
  
[[File:]]
+
[[File:ios_11_table_view_story_detail_running.png]]
  
 
Figure 30-5
 
Figure 30-5
Line 141: Line 141:
  
  
[[File:]]
+
[[File:ios_11_table_view_large_title.png]]
 
   
 
   
 
Figure 30-6
 
Figure 30-6
Line 149: Line 149:
  
  
[[File:]]
+
[[File:ios_11_table_view_detail_large_title.png]]
 
   
 
   
 
Figure 30-7
 
Figure 30-7

Revision as of 20:53, 10 April 2018

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

The objective of this chapter is to extend the application created in the previous chapter (entitled Using Xcode 9 Storyboards to Build Dynamic TableViews) and, in so doing, demonstrate the steps involved in implementing table view navigation within a storyboard. In other words, we will be modifying the attractions example from the previous chapter such that selecting a row from the table view displays a second scene in which a web page providing information about the chosen location will be displayed to the user. As part of this exercise we will also explore the transfer of data between different scenes in a storyboard.


Contents


Understanding the Navigation Controller

Navigation based applications present a hierarchical approach to displaying information to the user. Such applications typically take the form of a navigation bar (UINavigationBar) and a series of Table based views (UITableView). Selecting an item from the table list causes the view associated with that selection to be displayed. The navigation bar will display a title corresponding to the currently displayed view together with a button that returns the user to the previous view when selected. For an example of this concept in action, spend some time using the iPhone Mail or Music applications.

When developing a navigation-based application, the central component of the architecture is the navigation controller. In addition, each scene has a view and a corresponding view controller. The navigation controller maintains a stack of these view controllers. When a new view is displayed it is pushed onto the navigation controller’s stack and becomes the currently active controller. The navigation controller automatically displays the navigation bar and the “back” button. When the user selects the button in the navigation bar to move back to the previous level, that view controller is popped off the stack and the view controller beneath it moved to the top becoming the currently active controller.

The view controller for the first table view that appears when the application is started is called the root view controller. The root view controller cannot be popped off the navigation controller stack.

Adding the New Scene to the Storyboard

For the purposes of this example we will be adding a new View Controller to our storyboard to act as the second scene. With this in mind, begin by loading the TableViewStory project created in the previous chapter into Xcode.

Once the project has loaded we will need to add a new UIViewController subclass to our project files so select the File -> New -> File… menu item and choose the Cocoa Touch Class option from the iOS category. On the options screen, make sure that the Subclass of menu is set to UIViewController, name the new class AttractionDetailViewController and make sure that the Also create XIB file option is switched off. Click Next before clicking on Create.

Next, select the Main.storyboard file from the project navigator so that the storyboard canvas is visible. From the Object Library, select a View Controller and drag and drop it to the right of the existing table view controller as outlined in Figure 30-1. With the new view controller added, select it and display the identity inspector (View -> Utilities -> Show Identity Inspector) and change the class setting from UIViewController to AttractionDetailViewController.


Ios 11 table view attraction view controller.png

Figure 30-1


The detail scene has now been added and assigned to the newly created subclass where code can be added to bring the scene to life.


Adding a Navigation Controller

Once the application is completed, selecting a row from the Table View will trigger a segue to display the detail view controller. The detail view will contain a button which, when selected by the user, will navigate back to the table view. This functionality will be made possible by the addition of a Navigation Controller to the storyboard. This can be added by selecting the Attraction Table View Controller scene in the storyboard so that it highlights in blue, and then selecting the Xcode Editor -> Embed In -> Navigation Controller menu option. Once performed, the storyboard will appear as outlined in Figure 30 2:


Ios 11 table view navigation controller segues.png

Figure 30-2

Establishing the Storyboard Segue

When the user selects a row within the table view, a segue needs to be triggered to display the attraction detail view controller. In order to establish this segue, Ctrl-click on the prototype cell located in the Attraction Table View Controller scene and drag the resulting line to the Attraction Detail View Controller scene. Upon releasing the line, select the show option from the Selection Segue section of the resulting menu. The storyboard will update to display a segue connection between the table view cell and the view controller. In code that will be implemented later in this chapter it will be necessary to reference this specific segue. In order to do so it must, therefore, be given an identifier. Click on the segue connection between Attraction Table View Controller and Attraction Detail View Controller, display the Attributes Inspector (View -> Utilities -> Show Attributes Inspector) and change the Identifier value to ShowAttractionDetails.

In addition, a toolbar should have appeared in both scenes. Click in the Attraction Table View Controller toolbar area to select the Navigation Item component, display the Attributes inspector panel and change the title property to “Attractions”. Next, drag a Navigation Item view from the Object Library and drop it onto the toolbar of the Attraction Detail View Controller. Select the new item and change the title property in the Attributes inspector to “Attraction Details”:


Ios 11 table view navigation controller segues.png

Figure 30-3


Build and run the application and note that selecting a row in the table view now displays the second view controller which, in turn, has a button in the toolbar to return to the “Attractions” table view. Clearly, we now need to do some work on the AttractionDetailViewController class so that information about the selected tourist location is displayed in the view.

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

Modifying the AttractionDetailViewController Class

For the purposes of this example application, the attraction detail view is going to display a web view loaded with a web page relating to the selected tourist attraction. In order to achieve this, the class is going to need a UIWebView object which will later be added to the view.

In addition to the web view, the class is also going to need an internal data model that contains the URL of the web page to be displayed. It will be the job of the table view controller to update this variable prior to the segue occurring so that it reflects the selected attraction. For the sake of simplicity, the data model will take the form of a String object. Select the AttractionDetailViewController.swift file and modify it as follows to declare this variable and also to import the WebKit framework which will be used in the next step:

import UIKit
import WebKit

class AttractionDetailViewController: UIViewController {

    var webSite: String?
.
.
.

The next step is to add the Web View to the view controller. Select the storyboard file in the Project Navigator, and drag and drop a WebKit View from the Object Library onto the Attraction Detail scene. Resize the view so that it fills the entire scene area as illustrated in Figure 30-4:


Ios 11 table view web kit view.png

Figure 30-4


With the WebKit View selected in the storyboard canvas, display the Auto Layout Add New Constraints menu and add Spacing to nearest neighbor constraints on all four sides of the view with the Constrain to margins option disabled.

Display the Assistant Editor panel and verify that the editor is displaying the contents of the AttractionDetailViewController.swift file. Ctrl-click on the Web View and drag to a position just below the class declaration line in the Assistant Editor. Release the line and in the resulting connection dialog establish an outlet connection named webView.

When the detail view appears, the Web View will need to load the web page referenced by the webSite string variable. This can be achieved by adding code to the viewDidLoad method of the AttractionDetailViewController.swift file as follows:

override func viewDidLoad() {
    super.viewDidLoad()

    if let address = webSite,
        let webURL = URL(string: address) {
        let urlRequest = URLRequest(url: webURL)
        webView.load(urlRequest)
    }
}

Using prepare(for segue:) to Pass Data between Storyboard Scenes

The last step in the implementation of this project is to add code so that the data model contained within the AttractionDetailViewController class is updated with the URL of the selected attraction when a table view row is touched by the user. As previously outlined in Using Xcode 9 Storyboards to Build Dynamic TableViews, the prepare(for segue:) method on an originating scene is called prior to a segue being performed. This is the ideal place to add code to pass data between source and destination scenes. The prepare(for segue:) method needs to be added to the AttractionTableViewController.swift file as outlined in the following code fragment:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
   if segue.identifier == "ShowAttractionDetails" {

       let detailViewController = segue.destination
            as! AttractionDetailViewController

       let myIndexPath = self.tableView.indexPathForSelectedRow!
       let row = myIndexPath.row
       detailViewController.webSite = webAddresses[row]
    }
}

The first task performed by this method is to check that the triggering segue is the ShowAttractionDetails segue we added to the storyboard. Having verified that to be the case the code then obtains a reference to the view controller of the destination scene (in this case an instance of our AttractionDetailViewController class). The table view object is then interrogated to find out the index of the selected row which, in turn, is used to prime the URL string variable in the AttractionDetailViewController instance.

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

Testing the Application

The final step is to compile and run the application. Click on the run button located in the Xcode toolbar and wait for the application to launch. Select an entry from the table and watch as the second view controller appears and loads the appropriate web page:


Ios 11 table view story detail running.png

Figure 30-5

Customizing the Navigation Title Size

The inclusion of a navigation controller in this example caused a navigation bar to appear on each scene within the app. By default this includes a title navigation item and, when necessary, a “back” button to return to the previous view controller. Many of the built-in apps provided with iOS 11 now use a larger text size for these titles. The size of the title text within the navigation bar can be increased to conform with the general look and feel of the standard iOS apps by setting the prefersLargeTitles property on the navigation bar to true. To see this in action, modify the initialize method within the AttractionTableViewController.swift file to set this property:

func initialize() {
.
.    
    navigationController?.navigationBar.prefersLargeTitles = true
}

Run the app again and note that the title now appears in larger text:


Ios 11 table view large title.png

Figure 30-6


By default, this change will propagate down to any other view controllers displayed by the navigation controller. Selecting an entry from the table, for example, will show that the DetailViewController navigation bar has inherited the larger title property:


Ios 11 table view detail large title.png

Figure 30-7


To prevent the setting from applying to this view controller, a property is available on the navigation bar’s navigation item which specifies the display mode for the title. Modify the viewDidLoad method of the AttractionDetailViewController.swift file to set this property so that the larger title is not used on this screen:

override func viewDidLoad() {
    super.viewDidLoad()

    navigationItem.largeTitleDisplayMode = .never
    if let address = webSite {
        let webURL = URL(string: address)
        let urlRequest = URLRequest(url: webURL!)
        webView.load(urlRequest)
    }

}

The full range of settings for this property are as follows:

  • automatic – The default behavior. Causes the navigation item to inherit the size setting from the previous navigation bar item.
  • always – The navigation item title always uses large text.
  • never – The title always uses smaller text.

Summary

A key component of implementing table view navigation using storyboards involves the use of segues and the transfer of data between scenes. In this chapter we have used a segue to display a second scene based on table view row selections. The use of the prepare(for segue:) method as a mechanism for passing data during a segue has also been explored and demonstrated.

When a navigation controller is embedded into a storyboard, a navigation bar appears at the top of each view controller scene. The size of the title displayed in this navigation bar can be increased by setting a property on the navigation bar. To prevent this larger title from being inherited by other scenes in the navigation stack, simply change the display mode on the corresponding navigation item.


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book