How to Create an Xcode 4.0-style Window-based Application in Xcode 4.2
November 23, 2011 56 Comments
I’ve decided to get up to speed on iOS programming and, to help me with that, I bought Aaron Hillegass’s iOS Programming: The Big Nerd Ranch Guid 2nd edition. I’ve listened to Aaron on podcasts and have heard that his training method is fantastic. The book does seem to be unusually well written for a tech book but the problem I immediately ran into is that it was written for Xcode 4.0 and iOS 4.3 SDK. I have Lion with Xcode 4.2 and iOS 5 SDK. That’s part of the adventure of discovery and change in tech but unfortunately Apple removed the project type that Hillegass’s examples are based on which is a major stumbling block.
Hillegass uses the “Window-based Application” template for iOS as the basis for all of his projects. That template no longer exists in Xcode. The closest thing in Xcode 4.2 is “Empty Application”. However, that’s not quite the same thing because the now-defunct “Window-based Application” template generated a main window XIB view wired to generated controller but the “Empty Application” has no XIB. In order to make any sense out of the book, you have to create the XIB and wire it up yourself. This is no big deal to anybody with a little experience but to a newb like me, it took a bit of wandering in the wilderness at the Big Nerd Ranch forums to figure out how to manually get the project into the state that the exercises in the book will work.
How to Convert a new “Empty Application” into a “Window-based Application”
Start by creating a new iOS Application project using the “Empty Application” project. This will create a very similar project to the “Window-based Application” project described in iOS Programming 2/e with just a few differences:
- The main controller class that gets generated is “AppDelegate” rather than “<project-name>AppDelegate”. The
- There is no XIB view.
- The window property of AppDelegate doesn’t have the IBOutlet macro to make it visible to the Interface Builder tooling.
Prepare the controller to talk to the Interface Builder tooling
In the controller class interface definition of the we need to add the IBOutlet macro so that the tooling will recognize the controller. In your controller header file, AppDelegate.h, the line to modify begins with @property and ends with *window. Add IBOutlet in front of the UIWindow type as shown below.
#import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) IBOutlet UIWindow *window; @end
Save this change.
Update the didFinishLaunchingWithOptions: method
The auto-generated first line of code in the didFinishLaunchingWithOptions: method of AppDelegate.m prevents message routing from working properly. Comment it out as below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
Save this change.
Create the XIB file
Right-click on the folder containing your AppDelegate files and choose “Add File”. Select “Window” from the iOS User Interface group. Choose the appropriate device family—for the initial Quiz project that is iPhone. The default file name is Window.xib which works fine or you can name it MainWindow.xib to make it just like in the book.
Change the Class of the XIB file’s owner to UIApplication
Select Window.xib in the Navigator. Select the “File’s Owner” cube in the objects pane just left of the layout canvas and change the Class in the properties pane to UIApplication.
Add an object for the controller
Filter the tool pallet on the bottom right to “Objects and Controllers” and drag and drop an Object from the toolbox onto the object pane.
Set the class of the controller object
In the properties window, change the class to controller that was generated for your project by the template. That should be AppDelegate. The Object will automatically be renamed with a space added into the Pascal casing. (You can override this by putting something into the Label field of the Identity pane.)
Route the XIB delegate to the controller
Now we want to wire up the MVC message routing for the view. Select the “File’s Owner” cube in the object pane and control+drag the delegate outlet to the App Delegate object.
Route the controller object’s window outlet to the window object
Next perform a similar ctrl+drag of the window outlet from the App Delegate object to the Window object.
All done
Now our Empty Application project is set up just like a Window-based Application as described in iOS Programming 2nd Edition. The file names may be a bit different but that should have no practical effect. The AppDelegate inherits from UIResponder <UIApplicationDelegate> rather than NSObject<UIApplicationDelegate>. This doesn’t seem to be a problem, either.
Now that I have figured out how to create an wire up a main window XIB file, everything seems to work great as I follow along in the book.