Typically, every screen in an iOS app has an instance of UIViewController. They will usually control a hierarchy of UIViews.
Create an iOS Empty Application! Name it HypnoTime
Configure it like this.
We’re going to create some Objective-C classes that are View Controllers. It’s nice to not have to move them around after we create them. First, click on the HypnoAppDelegate.m file. The new class will be created below the currently selected file.
Create a new subclass of UIViewController.
Press ⌘-N. Click on Cocoa Touch in the left panel and Objective-C class in the right.
Name the class HypnosisViewController. We’ll use NSObject as the superclass for now.
Once you have a class, change the superclass to UIViewController in the .h file.
Arrange a Finder window so that it is in front of your project window in Xcode.
Navigate to your Hypnosister project in the Finder window and drag the HypnosisView.h and the HypnosisView.m files into your project.
A good place to drag them is right after your HypnosisViewController.m file.
After you let go of the mouse button you will see the following dialog. Make sure you check the two checkboxes shown.
Open the HypnosisViewController.m file and import the HypnosisView.h file.
Add an override of the loadView method to the HypnosisViewController.m file. Here’s the Modern Objective C way to do this.
Add code in the HypnoAppDelegate.m file to create an instance of the new view controller. You’ll also need to import HypnosisViewController.h.
Run the app! You should see your HypnosisView on your screen.
We will usually have lots of view controllers in an iOS app. Make another subclass of UIViewController the way you made the first one. Name it TimeViewController. First make a class that is a subclass of NSObject then rename the superclass to UIViewController.
For this controller we’ll make its view with Interface Builder. Create a new file, select iOS, User Interface, and then Empty.
Select iPhone on the next screen.
On the next screen name the file TimeViewController.xib.
Click on the .xib file. Notice that there is no View under Objects. We’ll add that next.
Demystifying the XIB: File’s Owner
This is a big topic that deserves its own page. Let’s take a little detour here:
Click on Images.xcassets in the Project Navigator.
Click on the + sign to add another image asset.
Select the New Image Set menu item.
Double-click on the new image set and name it Hypno.
Arrange a Finder window in front of your Xcode project and drag the Hypno.png file to the 1x box.
Drag the file named Hypno@2x.png to the 2x box. You won’t see the images because they are image masks. They are there.
Create another image set named Time and drag the other two images into its 1x and 2x boxes.
Add the following highlighted code to the HypnosisViewController.m file.
Notice that you don’t add the .png extension.
Add the following highlighted code to the TimeViewController.m file.
Run the app yet again. This is looking good!
View Controller Lifecycle
Initializing View Controllers
The main point from here is that these two lines of code are the same.
You can also be explicit about the name of the nib.
Notice that you don’t use the extension .xib in this method.
UIViewController and Lazy Loading
Add this method to the HypnosisViewController.m file.
Add this to the TimeViewController.m file.
The viewDidLoad method is run right after the view has been loaded by the system. We use this method to initialize things that can be reloaded.
Run the app and notice that only the HypnosisViewController loads it view at first.
Tap on the Time tab button and the other view is loaded.
Tap on both tab buttons again a few times. Notice that they are not being reloaded.
Tap on the Time button again and then select the Hardware→Simulate Memory Warning menu item in the iOS Simulator.
Um, it’s not working like in the book. That’s right, the rest of this section of the book is a bit out of date and we don’t need to worry about this much anymore.
As they mention in the book, we don’t code viewDidUnload any more. This was announced at WWDC 2012 and everyone one was happy about it.
Appearing and Disappearing Views
These methods are very handy when coding view controllers.
viewWillAppear: — Notifies the view controller that its view is about to be added to a view hierarchy.
viewDidAppear: — Notifies the view controller that its view was added to a view hierarchy.
viewWillDisappear: — Notifies the view controller that its view is about to be removed from a view hierarchy.
viewDidDisappear: — Notifies the view controller that its view was removed from a view hierarchy.
Add these methods to the TimeViewController.m file.
View Controller Subclasses and Templates
The templates that Apple provides are sometimes filled with lots of code we don’t need and commented out code. We will tend to delete most of it when making new view controllers.
FtMC: The main Function and UIApplication
Let’s look at the main function in the app’s main.m file.
This code creates an instance of the class UIApplication. It also sets your AppDelegate class as the delegate for it. The UIApplication instances then starts the run loop and you are up and running.
FtMC: Retina Display
Let’s look at some screen shots and photos of screens that are retina and non-retina.
First, a screenshot that is true size.
Zoomed screenshot, non-retina
Zoomed screenshot, retina
Zoomed photo of the screen, non-retina
Zoomed photo of the screen, retina
Images and icons in iOS development need to come in pairs. One of the images in the pair will be twice the size in pixels. Each pair starts with the same name and the larger one have “@2x” appended to the name.
Hypno.png — 30×30 pixels
Hypno@2x.png — 60×60 pixels
When we use the image we don’t have to specify which one to use. We just use the name “Hypno” and iOS will use the correct one for the device. A retina device will use the @2x version automatically.