In Part 1 of this series, we looked at how UIScreen, UIWindow, and UIView objects form the foundation of an iOS app’s user interface, and we built a simple app to demonstrate the relevant essentials of how they work together. In part 2, we’re going to expand our app to demonstrate the basics of how UIViewcontrollers interact with UIViews to create a working user interface.
We’ll be starting where we left off with the ViewMe project from Part 1, so you’ll want to open it up in Xcode. (You can download the ViewMe project here.)
Wiring a User Interface
At the end of Part 1, our app looked like Figure A. To make things more interesting, we’re going to change the text of the label and button in our code rather than in Interface Builder, and then to demonstrate how view controllers and views work together, we’ll wire things up so that when we press the button, the text of the label changes.
Click on MyViewController.xib in the Files and Groups pane to bring up our interface in Interface Builder. Then click on the Assistant Editor in the upper right corner of the Xcode Interface. (Figure B)
The Assistant Editor will display MyViewController.h in an adjacent pane as shown in Figure C.
Click on the label to select it, and then press the Control key and drag it from the label to just under the word “@interface” in MyViewController.h. When you release your finger from the mouse, the Connection dialog will appear. Type “myLabel” into the Name field and press Enter. You have now created an outlet named myLabel and connected it to the UILabel in the xib file. (Figure D)
Notice the property that is automatically generated for you by Xcode and tagged with the Outlet symbol (Figure E). This connection will be automatically established when the xib file is loaded, and our UIViewController will then be able to use it to interact with the label.
Repeat this process for the button and call the connection “myButton”. Next, resize the label and the button to be about half the width of the view by clicking on them and dragging the resizing handles to stretch them out. Set the label to center it’s text by selecting it and then clicking the middle alignment button in the Attributes Inspector. (Figure F)
The View Life Cycle
The UIViewController is responsible for the life cycle of the view it controls. This includes loading the view as necessary and notifying us when the view appears and disappears. At each of these points the view controller calls various methods that we can override to add our own functionality and modify the view’s appearance.
During the view load cycle, the view controller will call its loadView method followed by viewDidLoad. Most often you will only override viewDidLoad; it is rarely necessary to override loadView. After a view has been loaded it remains in memory, so viewDidLoad will typically be called only one time (as of iOS 6, views are no longer purged during low-memory conditions).
By contrast, the methods viewWillAppear and viewWillDisappear get called every time the view appears or disappears from the screen. This is a key distinction to keep in mind. If there are changes you wish to make when the view is initially set up, such as set the background color, you will want to do it in viewDidLoad. If you want your view to be updated with information that changes each time it appears (e.g. current temperature data in a weather app), you would do that in viewWillAppear.
Now let’s switch over to MyViewController.m and see how we can change our label and button when the view loads. Change the viewDidLoad method as shown below.
// Runs ONCE when the UIViewcontroller loads the view
self.myLabel.text = @"Acme Explosives";
[self.myButton setTitle:@"Press Me" forState:UIControlStateNormal];
When we build and run the app, it now appears as shown in Figure G. Both the button and the label are changed before they are displayed on the screen.
Now go back to MyViewController.m and add the following code below the ViewDidLoad method:
self.myLabel.text = @"Boom!";
Select MyViewController.xib in the Files and Groups pane. Right click on the button to bring up information about its properties. Click and drag from the “Touch Up Inside” event over to “File’s Owner”.
This will cause a list of available actions to appear, and in our case there is only one action available named “buttonPressed:”. Click on buttonPressed: to make the connection.
What we’ve done is create a method named “buttonPressed:” and associated it with our button so that it is called when the button is tapped. Technically, the “Touch Up Inside” event is fired whenever your finger leaves the button - hence the notion of “touch up”. If you look at the other event options available in Figure H, you’ll gain an appreciation for the sophistication and possibilities of UIButton. Declaring buttonPressed:with a return type of IBAction allowed Interface Builder to become aware of it and present it to us when we made the connection to our MyViewController subclass (File’s Owner).
If we now build and run the app, we find that our label changes when we press the button. (Figure I)
This example illustrates two fundamental concepts you will use repeatedly when developing your own apps:
- Views and their subclasses, such as UILabel and UIButton, make up the visible portion of your app.
- View controllers handle the logic behind the views, such as changing their appearance and responding to the events they generate.
Views and view controllers are the building blocks upon which all iOS apps are built. Together with Part 1 of this article, you should now have a clear understanding of how all of the various pieces work together to bring your iOS app to life.