nav controllers uinavigationcontroller. overview nav controller basics like a tabview controller, a...

42
Nav Controllers UINavigationController

Upload: tyrone-scott-neal

Post on 14-Dec-2015

219 views

Category:

Documents


1 download

TRANSCRIPT

Nav ControllersUINavigationController

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

And the detailed view is shown

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.

Changing the Detail View

Go to the storyboardClick on the segue from the secondLevelViewController to the detail view

In the attributes inspector change the identifier to “showDetail”