nav controllers uinavigationcontroller. overview nav controller basics like a tabview controller, a...
TRANSCRIPT
Overview
Nav Controller basicsLike a tabview controller, a navViewController manages views
A navigationViewController uses a stack
navigationViewControllers are good for hierarchies
The navigation controller is mostly used on iPhone apps for iPad apps the splitViewController is used instead.
ReferenceApple Developer Reference
Overview
Nav Controller basicsWhen you create a navigationController project, the first view that is displayed is created
Called the masterViewController.swift in Xcode
This is the root controller or main controller.
In the Xcode nav controller project one of the subsidary views is provided.
It’s called the detailedViewController.swift
When a row in the root controller is selectedA corresponding view controller is pushed onto the controller stack
The view associated with the pushed view controller appears
Navigation Stack
Initially the masterViewController view is displayed and pushed on the stack
MasterViewController
Navigation Stack
When a row is pressed, a detail view controller is pushed onto the stack
MasterViewController
DetailViewControler
Navigation Stack
MasterViewController
DetailViewControler
When the return button is pressed, the detailedViewController is popped off the stack.
Navigation Stack
And the top of stack controller view (masterViewController in this case) is displayed.
MasterViewController
Nav View
A navigation controller contains a navigation bar and a view by default.
Navigation ControllerTable view cell
The Xcode navigation project uses a table view
The Xcode navigation project has a navigation bar. These buttons are in the default project.
The navigation controller has a title
Nav ViewWhen a row is selected a detailed view is displayed.
Detailed view
A button back to the previous controller is automatically provided.
The navigation bar title changes
More
The detailViewConroller can, itself, hold a tableView.
When rows of this table view are touched, we can launch a third level view.
The app
We’ll create a navigation app that uses tables for the detail view
Create a new project, choose “Master-Detail Application”
make sure that you create a project just for iPhones.
Do not create a “universal” project; these slides won’t work with with “universal” projects.
What did you get?
Look at the file navigator. Same files.appDelegate, master and detail view controllers and a storyboard.
What did you get?
appDelegate, master and detail view controllers with their nibs.
MasterViewController controls the root view that is initially displayed
DetailViewController controls the detail view that is displayed when a row is selected. You might need many different ViewControllers if you have many different views for the different rows.
What did you get?
appDelegate, master and detail view controllers with their nibs.
Main Storyboard. Contains a UITableView
Run
You can click on a row and a new entry will be added (with the time clicked).
when you click on the row, a detail view appears with the time from the row.
GoalCreate a new view that will load when a row in the MasterView is clicked
This view will be a table itself
When a row in this second level view is clicked, load the detail view
Simplify
We’ll take out the editing and add new row functions from the nav controller
Change the viewDidLoad method by deleting the code:
override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.navigationItem.leftBarButtonItem = self.editButtonItem()
let addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "insertNewObject:")
self.navigationItem.rightBarButtonItem = addButton }
Simplify
Delete the insertNewObject method
func insertNewObject(sender: AnyObject) {
objects.insertObject(NSDate(), atIndex: 0)
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
SimplifyDelete the tableView commitEditingStyle method
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
objects.removeObjectAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
Simplify
Delete the tableView canEditRowAtIndexPath method
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
UpdateNow update the MasterViewController
Change the mutable array to a static array of strings
let objects = NSMutableArray()
To
var objects : [String] = ["Windows", "Apple", "Sun"] let appleComp : [String] = ["MacBook","MacBook Pro","iMac","Mac Mini","Mac Pro"] let winComp : [String] = ["Dell Inspiron 20 3000", "Dell Inspiron 23 5000", "HP Envy 810", "HP Pavillion 23 TouchSmart", "Lenovo M83", "Lenovo P500"] let sunComp : [String] = ["Oracle Solaris 10", "Oracle Solaris 11"] var compModels : [[String]] = []
This will eventually hold [winComp, appleComp, sunComp] but can’t initialize a property with another property
These 3 lists will be used for the next level table
The objects array will be used for the table in this view controlleer
Update
Now update the MasterViewControllerChange the viewDidLoad method
override func viewDidLoad() {
super.viewDidLoad()
// have to do this here; can't initialize a property with other properties when you create it
compModels = [winComp, appleComp, sunComp]
} Store the lists of computer models in the compModels property
Update
Now update the MasterViewControllerChange the prepareForSegue method
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "goToSecondLevel" { if let indexPath = self.tableView.indexPathForSelectedRow() { let object = compModels[indexPath.row] (segue.destinationViewController as SecondLevelViewController).CompModels = object } }
}
We’ll store the appropriate computer list in the secondlevelViewController property
Rename this segue in the storyboard
You’ll get an error about SecondLevelViewController. We’ll fix this later
UpdateNow update the MasterViewController
Change the tableView method
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let object = objects[indexPath.row] as NSDate
cell.textLabel!.text = object.description objects[indexPath.row] return cell
}
Delete “as NSDate” We’ll just be using strings
Change to an index into our objects array
Run
See a static table (if you comment out the line with an error)
You can click on the rows, but the detail view will just have generic text.
Uncomment the line that had the error; we’ll fix that now.
Create a new view controller
Create a new file. Call it “SecondLevelViewController”
Choose “iOS Source”
Choose the type to be a Cocoa Touch class
make it a subclass of a UITableViewController
do NOT create a XIB file
Make the language “Swift”
Make sure the target checkbox is
Clicked.
Be carful that the name is correct!!
Creating a new view
Go to stroyboard and drag a Table View Controller to the editing area
Go to the view navigator and select the new Table View Controller. Go to the identity inspector and change the Custom Class to class “SecondLevelViewController” (you may have to type this in)
Creating a new view
With the Table View Controller still selected, go to the Connections Inspector and ensure that the dataSource and delegate are the “SecondLevelViewController” (they may already be connected)
Creating a new view
Now we need to give the Table Cell View the same identity as we use in the SecondLevelViewController code.
click on the Table Cell in the navigator
Go to the identity inspector and make the Restoration ID the string “compCell”(this step is not really necessary)
Next go to the attributes inspector and change the style to “Basic” and the Identifier to “compCell”
Connecting
Finally, we have to connect the original table to the new Table View Controller and the new Table View Controller to the detail view
Click on the segue between the original table view to the detail view and delete it.
Connecting
Finally, we have to connect the original table to the new Table View Controller and the new Table View Controller to the detail view
Now control-drag from the Table View Cell in the Master Scene to the new Table View Controller body and choose Selection Segue Show from the pop-up dialog box.
Changing the Segue
Go to the storyboardClick on the segue from the firstLevelViewController to the secondLevelViewController view
In the attributes inspector change the identifier to “goToSecondLevel”
Creating the second level view
Go to SecondLevelViewController.swift file and add
class SecondLevelViewController: UITableViewController { var CompModels :[String] = []
Enables this class to be the datasource and delegate of the table
The array CompModels will hold the data for the table. This data will be set when the first level controller segues to this controller.
Creating the second level view
Go to SecondLevelViewController.swift file and change the table dataSource methods
override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return CompModels.count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell = tableView.dequeueReusableCellWithIdentifier("compCell", forIndexPath: indexPath) as? UITableViewCell if (cell == nil) { cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "compCell") } let object = CompModels[indexPath.row] cell!.textLabel?.text = CompModels[indexPath.row] return cell! }
Return number of sections and rows
Gets a cell for a given row
Connect 2nd level table to detail view
Go to the storyboardControl drag from the table cell (which we labeled compCell ) in the second level view controller scene to the body of the detail view controller
choose
Selection Segue Show
from the pop-up dialog box.
Run
You should be able to click on a row in the Master view and go to the new table view and then click on a row in the new table view and go to the detail view.
Problem: the detail view does not change based on the row selected.
Yet to be done: customize the detail view.
Creating the second level view
Go to SecondLevelViewController.swift file and add a segue method
changes an instance variable in the DetailViewController class when the segue is getting ready to fire.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "showDetail" { if let indexPath = self.tableView.indexPathForSelectedRow() { let object = CompModels[indexPath.row] (segue.destinationViewController as DetailViewController).detailItem = object } } }
This method is called just before the segue is taken
If we’re going to the detail view…
Then get the text from the CompModels array and use it to change the detailItem in the detail view.
Changing the Segue
Give the segue you just created a nameClick on the segue from the secondLevelViewController to the deatilView
In the attributes inspector change the identifier to “showDetail”
Run!
Should get the detailViewController view when click a row at the second level.
The text box in the detailViewController should be the name from the row!
Complications
Can you go to different detail views from different rows?
Yes, but will need to have a different cell prototype in the storyboard for each type of detail view.