Beginning iOS Development

Course No. 10-152-143

Chapter 13 — UIPopoverController and Modal View Controllers

Let’s start learning how to write iPad apps.

Universalizing Homepwner

  • The first step is to make the Homepwner app universal. Make a copy of the finished chapter 12 version.
  • Open the project in Xcode. Click on TARGETS→Summary and change the device to Universal.

  • Change the simulator to iPad and run the app.

  • Sweet! It just works. However, the detail page doesn’t look so good.

Determining Device Family

  • For now all we’ll do is change the background color if we’re running on the iPad.
    • Note: This is an important technique to know, but it should not be used very often. We’re doing it this way for this project as a learning exercise.
  • Open the DetailViewController.m file and modify the viewDidLoad method to this.
  • Now the background color matches the table view.

  • The key is this line.
  • We can tell if we are running on an iPad by checking the user interface idiom. Sometimes this is the only way we can solve some universal issues.
  • Next we need to change the autorotation behavior. iPad users expect to be able to rotate their devices to any orientation.
  • First, we need to select TARGETS→Summary and click on the Supported Interface Orientations icons so that all are on.

  • Then we need to add this method to both ItemsViewController.m and DetailViewController.m.
  • Run the app and it will now rotate to all orientations on the iPad.


  • The iPad has a special controller to display modal views. Here’s some examples.

  • These are examples of the UIPopoverController. They allow us to have modal views which don’t take up the entire screen. Here’s a simple popover controller with no contained view.

  • Popover controllers are useless by themselves. We need to create another view controller to use inside the popover. We’ll do this first with the image picker controller we use to take pictures and select images.
  • Open the DetailViewController.m file and add this property to the class extension.
  • In DetailViewController.m modify the takePicture: method. Comment out the last line and add following code at the bottom of the method.
  • Run the app on an iPad and you will see this when you tap the camera button.

  • Notice that the camera does not have a cancel button like it does on the iPhone? Popover controllers are dismissed in different ways. Let’s look at the delegate for the popover controller to see how it’s done.

UIPopoverControllerDelegate Protocol

  • Tasks
    • – popoverControllerShouldDismissPopover:
    • – popoverControllerDidDismissPopover:
  • Just two methods and neither are required.
  • If you tap anywhere on the screen off of the popover it is dismissed. That’s automatic. If you want to do something when that happens you have to implement popoverControllerDidDismissPopover:.
  • First, add the protocol to the DetailViewController class.
  • Next, modify the imagePickerController:didFinishPickingMediaWithInfo: method in the DetailViewController.m file. Comment out the last line of the method and add this code at the bottom of the method.
  • Now when a user tap off the popover it will be dismissed and deleted. However, there’s a crashing bug we have to fix. If the user taps on the camera button while the popover is open then the app will crash. What we want to happen is for the popover to be dismissed.
  • Add this code to the very top of the takePicture: method.
  • This code tests to see if the popover is visible and dismisses it if it is.

More Modal View Controllers

  • There are other types of modal views on the iPad. We’ll use one of them to be able to enter the data for a new item. We’ll also reuse the DetailViewController for this so we don’t have to create another one.
  • To enable this dual-use we’ll add a new initializer named initForNewItem:. Open the DetailViewController.h file and add this method declaration.
  • Now add this implementation of the method near the top of the DetailViewController.m file.
  • Next, we’ll make it illegal to use the normal designated initializer, initWithNibName:bundle:. Modify the method to be this.
    • If another developer tries to use this method they will get an error in the console log that tells them the correct method to use.
  • If you run your app now you will see the exception. To fix this open the ItemsViewController.m file and modify the tableView:didSelectRowAtIndexPath: method.
  • Now we’re back to normal with a new initializer. This sets us up for adding a new item with a modal view. While still in the ItemsViewController.m file, modify the addNewItem: method to be like this.
  • Run the app, tap on the add button and you’ll see the modal window come up from the bottom of the screen.

    • Tapping the Cancel or Done buttons won’t work yet, that’s next.

Dismissing Modal View Controllers

  • To dismiss the modal detail controller we need to use a built-in feature when one view controller presents another controller. Whenever the presentViewController:animated:completion: method is used the presented and presenting controllers get pointers to each other. When we tap the done button we will run code in the DetailViewController. However, only the ItemsViewController can dismiss the modal view. There has been a change in how to do this since the book was written.
  • Let’s implement the save: method to see how this works. Open the DetailViewController.m file and add this method.
    • Notice that we are sending this message to self. The book has us send the message so self.presentingViewController. This is no longer necessary. The modal view controller knows what controller presented it and passes the message along to the right object.
  • Now for the Cancel button. Add this method, too.
    • First, we remove the item that was created when we tapped the add button.
    • Then we dismiss the modal view controller.
  • Let’s switch the style of the modal view to what’s called a form sheet. Modify the addNewItem: method by adding the highlighted line.
  • Run the app and add a new item.

  • Looks good! However, there’s a problem. Notice that the new items don’t appear in the list when the Done button is tapped? viewWillAppear: never gets called. We need another way to do this.
    Blocks FTW!

Completion Blocks

  • This will be a brief introduction to blocks in C. This is an advanced concept so we’ll start learning this gently. At this point just type in the code, listen to the explanation, read the book, and we’ll get back to this later.
  • We’ve been using methods like this with a block parameter.
  • And this one.
  • What does that word completion mean? That parameter expects an argument that’s a block. Let’s look at the declaration for the dismissViewControllerAnimated:completion: method.

Defining Block Properties

  • This is a declaration of a block. Pretty scary, eh? The syntax is strange, but the concept is simpler. A block is an object that is also a chunk of code. We can treat blocks like all other data. We can assign them to variables and send them to other methods as an argument.
  • If that doesn’t make sense now, don’t worry, it will someday.
  • Let’s just code it first. Open DetailViewController.h and add this property.
    • This needs to be a public property so that it can be set from outside the class.
  • Let’s break this down a bit so the syntax is not so cryptic. We’re defining a property that is also a function. The first void is the return type.
  • The ^ symbol is telling the compiler that this is a block.
  • The name of the block property is dismissBlock.
  • The (void) statement is the parameter list. We have no parameters so this is void.

Creating a Block

  • The code that will be assigned to this property will be defined in the ItemsViewController.m file. Edit the addNewItem: method and add the highlighted code.
  • Let’s look at this code. The block starts with ^{ and ends with };. That’s a new syntax that Apple added to C. There were no other symbols available so they picked the ^.
  • In between the start and the end of the block we can put code. Any code. This is just a function at this point.
  • This is the key point of blocks. Here we are assigning this code to the property of another class. The class won’t know what’s in the block and it can run the code when it wants to.

Calling a Block

  • How do we run this code? In this case we’ll use the concept of completion. We assign our block to the completion parameter. In the DetailViewController.m file edit the save: method so it looks like this.
    • The completion parameter was nil. Now it’s self.dismissBlock.
  • Completion means that when the method you are calling finishes run the code in the completion parameter.

  • The beauty of this is that the DetailViewController class does not know what the code is, it just runs it.
  • The dismissViewControllerAnimated: method is part of the UIViewController written by Apple. It doesn’t know what the code in the block is. It just runs it when it’s done.
  • Run the app and you’ll see that when you add a new item and tap the Done button, the new item is added to the list.
  • We’ll come back to this later. Don’t worry if it doesn’t make sense, just get it to work at this point.

Modal View Controller Transitions

  • Modal views can be shown with different animations. Here’s the enum that defines them.
  • We can change to one of these by setting the modalTransitionStyle property of the view that is getting shown. One tricky aspect of this is that the view controller that is being shown is actually the navigation controller, not the DetailViewController.
  • Edit the addNewItem: again and add the highlighted line.
  • Run the app and the modal view appears with a different animation.

  • Experiment with the other styles. You’ll notice that you can only use page curl with a full screen view.