Things wot I learnt from Stanford – iPad & iPhone App Development – Fall 2011 – Lecture 6

Multiple MVC’s and Segues

A common design pattern is for an object to pass a reference to itself (using ‘self’) when sending a message to a delegate so that the delegate can ask our object for more information if they want. For example in the @protocol definition shown below, the FaceView control will set the sender parameter to self when it calls the delegate which handles the smileForFaceView: message:

Fig 1

An object sends a reference to itself to the handler.

If you want the fact that your class implements a @protocol to be kept private (i.e. it’s not of interest to an external developer), you are allowed to specify the @protocol name in your private @interface declaration  – i.e. the one (normally) in your “.m” file rather than in the header “.h” file. See screenshot.

Fig 2

Declaring a protocol implementation privately

CGPointZero is a handy, predefined constant for specifying a point of (0, 0) for example when resetting translations passed to gesture handlers. See screenshot.

Fig 3

Using CGPointZero to reset a translation in a gesture recognizer.

One MVC (Model, View Controller) should never control more than one screen. If we need to add another screen we should add a new MVC.

Fig 4

Multiple MVCs working together to show multiple screens.

We need a “controller of controllers” to switch between multiple MVCs (or screens) for example a UINavigationController. These are sometimes referred to as “container controllers”.

Fig 5

A UINavigationController acts as a “controller of controllers” and allows us to co-ordinate between multiple MVCs

Fig 6Fig 7A UINavigationController is a subclass of UIViewController with its own view which can have a title bar and always has an area below it in which to show the view from another MVC. It has no model, it is purely a UI controller.

It has a rootViewController @property which can point to another MVC. This controls what appears in its view (the white area in the screenshots above). It actually “embeds” that MVC’s view into this area. It will change the bounds of your MVC’s view to fit (note your “springs” and “struts” defined in Interface Builder and the view’s contentMode therefore become important during this resizing).

Segues

Only in iSO 5 and later. To create a segue in your Storyboard, hold down Ctrl and drag from the source object (e.g. a button) to the destination view controller.

Fig 8

Creating a Segue

Segues always instantiate a new instance of a view controller. Segues ALWAYS instantiate a NEW instance of a view controller. That’s not a Ctrl-V stutter- I said it twice as it’s important! They always create a new instance from scratch. This allows iOS to dispose of the destination view controllers and free up memory as soon as they’re dismissed.

Segue styles (at the time of writing) can be Push, Modal or Custom (your own subclass of UIStoryboardSegue). Push is used inside a UINavigationController. The iPad also supports Replace which allows you to replace the right-hand view of a UISplitViewController. The style can be set in the Storyboard by selecting the segue and choosing it from a list as in the slide below.

Fig 9

Specifying a segue style (and identifier)

The slide below shows how you can embed your view controller (often your startup one) in a Navigation Controller using the Storyboard interface. The process is similar for embedding within a Tab Bar Controller.

Fig 10

Embedding your view controller in a Navigation Controller.

This leads to this…

Fig 11Your view controller is added to the Navigation Controller as the rootViewController @property (an outlet).

Fig 12Here’s an example of how your view could appear embedded within a Navigation Controller. Notice that the “back” button takes it’s label text from the title @property of the previous UIViewController and the title of the current View Controller is shown at the top.

Fig 13

Using a UINavigationController

A really quick way to set the title @property is just to double-click it directly in the Storyboard and type it in.

Fig 14

Entering the title @property for your View Controller.

Pressing the “Back” button pops a pushed MVC back to the original, source MVC, but you can also do this programmatically using the UINavigationController instance method:

– (void) popViewControllerAnimated: (BOOL) animated

It’s rare but sometimes handy to call this. In this example, we actually call this function from within the controller on screen – i.e. the one to be “popped” – when its display is no longer required.

Fig 15

Popping a view controller programmatically.

All UIViewControllers have a navigationController @property. If the controller is not embedded in a Navigation Controller this will be set to nil. There are similar properties to access other container controllers such as tabBarController.

Triggering a segue from code:

Fig 16When a segue fires, the destination view controller is instantiated with all its outlets then the following message is sent to the source view controller to give it the chance to pass it information:Fig 17A common pattern here is to set ‘self‘ as the delegate for the the new, destination controller using the id type. Using the id type is important! DO NOT PASS THE ACTUAL TYPE. Always treat the new View controller as you would treat a view – give it as little information as possible. This approach greatly enhances the portability (“re-usability”) of your controller and code.

You can also instantiate a view controller programmatically using the Storyboard method:

– (id)instantiateViewControllerWithIdentifier:(NSString *)identifier

You can obtain a reference to the Storyboard by calling self.storyboard – as long as self was created from the same Storyboard.

Fig 18

Instantiating a view controller from the Storyboard programmatically.

Note the use of pushViewController in this example which assumes the current controller is embedded in a Navigation Controller.

Tip: Did you know a UILabel control can have more than one line of text simply by selecting it in your Storyboard and setting the “Lines” attribute to a number greater than 1?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s