iOS 5 Programming with Xcode

iOS 5 Programming Using Xcode 4.2 with Mac OS 10.7 Lion

  • Download and install Xcode 4.2 Lion version (with iOS 5 SDK) from the Apple Developer Network
  • Start Launchpad in the Mac OS Lion's dock
  • Select Developer -> Xcode
  • Select "Create a new Xcode project"
  • Select iOS -> application on the left & then "Single View Application" for an introductory level iOS application
  • Follow the screen instructions
    • Name the project as HelloNib
    • For our first application, un-select "Use storyboard" to use NIB to design the user interface
    • Later, we will use Storyboard for another application (Storyboard makes page flow design easier then NIB)
  • Create a new directory Developer under the user home directory (~/Developer)
  • Choose ~/Developer for the project location

Generated Main Program

#import <UIKit/UIKit.h>

#import "HelloNibAppDelegate.h"

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([HelloNibAppDelegate class]));
    }
}
  • @autoreleasepool allows the use of Automatic Reference Counting (ARC)

Using Nib file to Create the User Interface

Xcode creates the following application delegate header file

HelloNibAppDelegate.h
#import <UIKit/UIKit.h>

@class HelloNibViewController;

@interface HelloNibAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) HelloNibViewController *viewController;

@end
@class HelloNibViewController;
  • Create a forward declaration for the view controller
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) HelloNibViewController *viewController;
  • Declare accessor to access the UI window & view controller
  • strong is a new feature in iOS 5 Automatic Reference Counting (ARC) which behave the same as retain in iOS 4

The Application Delegate Implementation file created

HelloNibAppDelegate.m
#import "HelloNibAppDelegate.h"

#import "HelloNibViewController.h"

@implementation HelloNibAppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        self.viewController = [[HelloNibViewController alloc] initWithNibName:@"HelloNibViewController_iPhone" bundle:nil];
    } else {
        self.viewController = [[HelloNibViewController alloc] initWithNibName:@"HelloNibViewController_iPad" bundle:nil];
    }
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
}

- (void)applicationWillTerminate:(UIApplication *)application
{
}

@end
@synthesize window = _window;
@synthesize viewController = _viewController;
  • Implement the accessors for window and view controller
  • Declare _window, _viewController as the internal instance variable name for window & viewContoller respectfully
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  • Initialize a window for the application display
    self.viewController = [[HelloNibViewController alloc]
         initWithNibName:@"HelloNibViewController_iPhone" bundle:nil];
    self.window.rootViewController = self.viewController;
  • Initialize a custom view controller with the specific Nib file name and bundle to be used
  • Set the view controller to be the root controller for the application
    [self.window makeKeyAndVisible];
  • Make the application window visible

The following delegate are called when transition between different states (active, background, terminate)

application:didFinishLaunchingWithOptions:
applicationDidBecomeActive:
applicationWillResignActive:
applicationDidEnterBackground:
applicationWillEnterForeground:
applicationWillTerminate:
  • System calls application:didFinishLaunchingWithOptions: after the application is launched
  • When a user presses the Home button or another application is launched, the application transitions to the inactive state and then to the background state with the calls applicationWillResignActive: and applicationDidEnterBackground:
  • System calls applicationWillEnterForeground: & applicationDidBecomeActive: when the application becomes active

Run the XCode 4.2 simulator for iOS 5 application

  • In the top left, select the simulating device to run the application - HelloNib > ... (Use iPhone 5.0 simulator for this exercise)
  • Hit Run button on top left to run the application in the simulator
  • A white screen will be seen when the application run
  • Quit the simulator when it is done (Cmd-q)

Adding Visual Elements with Interface Builder in Xcode 4.2

  • Click on the iPhone .xib file
  • Make sure the utility panel (on the right side) is shown
    • If not, click the show the utilities icon on the top right above the word "view"
  • In the lower utility panel, select the object library by clicking "Show the Object library" icon
  • Drop a Text Label, a Round Rect Button & a Text Field to the view editor in the middle panel
  • Select the Text Field just created
  • In the top section of the utility panel, select "Show the Attributes inspector")
  • In the placeholder field, put "Enter your name here"

Create and Connect Outlets & Actions in Xcode 4.2

  • On the top right corner, select the "Show the Assistant editor" above the word Editor
    • The editor will display both the UI designer and the view controller header file (HelloNibController.h)
  • Control and drap the Label element to the header file (HelloNibController.h) between the line @interface & @end
    @interface HelloNibViewController : UIViewController
    
    @end
    
  • In the popup
    • Enter a name displayName for the Outlet
    • The following code will be generated automatically
      HelloNibViewController.h
      @interface HelloNibViewController : UIViewController {
          ...
          UILabel *displayName;
          ...
      }
      
      @property (nonatomic, strong) IBOutlet UILabel *displayName;
      
      HelloNibViewController.m
      @synthesize displayName;
      
      • The header file declare an IBOutlet for the Label
      • The Controller displays a text in the Label through the displayName property
      • IBOutlet acts as a marker used by Interface Builder for to connect UI objects with the application code
      • IBOutlet does not generate any runtime code
      • @synthesize implements the new property displayName automatically
    • Set all IBOutlet to nil when a view is unload
      HelloNibViewController.m
      - (void)viewDidUnload
      {
          [self setDisplayName:nil];
          ...
      }
      
  • Control and drap the button to the HelloNibController.h
    • Select Action in the Connection box
    • Enter a name "hello"
    • Select Type UIButton
    • Select "Touch Up Inside" for Event (Send an event when the button is up)
    • The following code will be generated automatically
      HelloNibViewController.h
      - (IBAction)hello:(id)sender;
      
      HelloNibViewController.m
      - (IBAction)hello:(id)sender {
      }
      
      • Create an action method declaration & a skeleton in the implementation file
      • IBAction acts as a marker to tell Interface Builder to treat the method as an action
  • Control and drap the Text field to the HelloNibController.h
    • Enter inputName for the name
    • Create the IBOutlet for the text field
      @interface HelloNibViewController : UIViewController {
          ...
          UITextField *inputName;
          ...
      }
      
      @property (nonatomic, strong) IBOutlet UITextField *inputName;
      
      @synthesize inputName;
      
      - (void)viewDidUnload
      {
          ...
          [self setInputName:nil];
          ...
      }
      

Implement the iOS View Controller code to handle Actions

Add a delegate for the text field when a user hit the return after enter text in the Text Field

  • Control click in the text field
  • Drap the popup's delegate round button to the File's owner on the panel to the left of the editor (The yellow cube)

Implement the code to handle the button up action for the button

HelloNibViewController.h
- (IBAction)hello:(id)sender {
    self.displayName.text = self.inputName.text;
}
  • Set the user entered text to the display field (Label)

Implement the delegate handling the action when an user hit a return in the text field

HelloNibViewController.h
@interface HelloNibViewController : UIViewController  <UITextFieldDelegate>{
   ...
}
  • Declare the controller supports the UITextFieldDelegate which handle events from the Text Field
HelloNibViewController.m
- (BOOL)textFieldShouldReturn:(UITextField *)text {
    if (text == self.inputName) {
        [text resignFirstResponder];
    }
    return YES;
}
  • When "Enter your name here" text field received a "return" key, lose the first responder status
    • Lose the first responder status will dismiss the keyboard on the screen

Test the application again

Memory Management with the new Automatic Reference Counting (ARC) in iOS 5

Automatic Reference Counting (ARC) for Objective-C removes the programmer requirement to manage memory manually

  • No need to call retain, release, autorelease anymore
  • No need to release objects in dealloc - in most cases, no need to implement dealloc

To use ARC, Xcode use @autoreleasepool to mark the new autorelease block

main.m
@autoreleasepool
{
   ...
}
  • Compiler will generate the reference counting code automatically

New attributes for the Properties in Automatic Reference Counting (ARC)

New property attributes when using ARC

@property(strong) MyClass *obj;

Same as below without ARC

@property(retain) MyClass *obj;

Weak reference in Automatic Reference Counting (ARC)

@property(weak) MyClass *delegate;
  • Similar to below without ARC
    @property(assign) MyClass *delegate;
    
  • Except when the MyClass instance is deallocated, delegate will set to nil

View Controller

Life Cycle Delegate for View

Different delegate for view to appear or unload

- (void)viewDidLoad
- (void)viewDidUnload
- (void)viewWillAppear:(BOOL)animated
- (void)viewDidAppear:(BOOL)animated
- (void)viewWillDisappear:(BOOL)animated
- (void)viewDidDisappear:(BOOL)animated

viewDidLoad

  • Use this delegate to initialize and load the model/data to be manipulated by the view

Supported Device Orientation

Delegate indicates what device orientation is supported

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
    } else {
        return YES;
    }
}

iOS 5 Programming with XCode 4.2 using Storyboard

Storyboard provides a super set feature over NIB

  • The Storyboard editor configures multiple view controllers in one editor
    • Allow a developer to define the transition from one screen to another screen
    • Instead of creating visual elements one screen/view controller at a time like the NIB file

To create an application:

  • With 2 pages
  • When hit a button on the first page, the application transit to the second page

Follow the steps below:

  • Create a new iOS 5 application project
    • Make sure the storyboard is selected when asked
  • Select the iPhone .storyboard file
    • An initial view controller representing the root view is already created
  • Open the utility panel if not done (Upper right icon above the word view)
  • Add a button to the view controller
  • Select the object library in the lower right window
  • Drap a new View Controller to the editor
  • Control click on the button in the first view controller
  • In the popup box, drap the circle in performSegueWithIdentifier to the second view controller
  • Add an identifier in the attribute inspector
  • Run the application
    • Click on the button will lead you to the second screen