In such case, we would have to load our view controller from that .xib file by passing the .xib file's full name to the initWithNibName parameter of the initWithNibName:bun dle: method o
Trang 1@synthesize window = _window;
@synthesize rootViewController;
3 Now find the application:didFinishLaunchingWithOptions: method of the app
delegate, inside the implementation (.m) file, and instantiate the view controller
and add it to our window:
- (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.window = [[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]];
Now if you run your app on the simulator, you will see a black screen The reason is
that our view controller's view doesn't have a background color yet so go to the ViewController.m file and find the viewDidLoad method which is in a state similar to this:
Trang 2self.view.backgroundColor = [UIColor whiteColor];
}
Go ahead and run the app on the simulator You will now see a plain white view onthe screen Congratulations, you just created a view controller and now you have access
to the view controller and its view object
While creating the view controller (Figure 2-26), if you had selected the With XIB for
user interface checkbox, then Xcode would have also generated an xib file for you In such case, we would have to load our view controller from that xib file by passing the xib file's full name to the initWithNibName parameter of the initWithNibName:bun dle: method of the view controller, like so:
- (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.window = [[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]];
If you did create a xib file while creating your view controller, you can now select on
that file in Xcode and design your user interface with Interface Builder
See Also
XXX
2.8 Implementing Navigation with UINavigationController Problem
You would like to allow your users to move from one view controller to the other with
a smooth and built-in animation
Solution
Use UINavigationController
Trang 3If you've used an iPhone, iPod Touch or an iPad before, chances are that you havealready seen a navigation controller in action For instance, if you go to the Settingsapp on your phone and then press an option such as Wallpaper (Figure 2-28), you willsee the Settings' main screen get pulled out of the screen from the left and the Wallpaperscreen pushing its way into the screen from the right That is the magic of navigation
controllers They allow you to push and pop view controllers, where pushing a view
controller means pushing it into the stack of view controllers and popping a view troller means removing that view controller from the stack The view controller on top
con-of the stack is the top view controller and that is the view controller which the user sees
at any given moment So we can conclude that only the top view controller gets played to the user unless that view controller is popped or another view controller ispushed onto the stack in which case the new view controller becomes the top viewcontroller and the one getting displayed to the user
dis-Figure 2-28 Settings view controller pushing the Wallpaper view controller
Trang 4Now we are going to add a navigation controller to our project but we need a projectfirst Please follow the instructions in Recipe 2.7 to create an empty application with asimple view controller In this recipe we will expand on the recipe in Recipe 2.7 Let's
start with the h file of our app delegate:
#import <UIKit/UIKit.h>
@class RootViewController;
@interface Implementing_Navigation_with_UINavigationControllerAppDelegate
: UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) UINavigationController *navigationController;
@property (nonatomic, strong) RootViewController *rootViewController;
- (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.window = [[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]];
Trang 5return YES;
}
Now let's run our app in the simulator:
Figure 2-29 An empty view controller displayed inside a navigation controller
The first thing you might notice in Figure 2-29 is the bar on top of the screen Thescreen isn't plain white anymore There is a bar on top What is that, you might ask?Well, that is a navigation bar We will be using that bar alot for navigation, placingbuttons there and etc That bar is also capable of displaying a title Each view controllerspecifies a title for itself and the navigation controller will automatically display that
Trang 6title once the view controller is pushed into the stack Let's go to our root view troller's implementation file and inside the viewDidLoad method set the title property
con-of our view controller to First Controller:
- (void)viewDidLoad{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"First Controller";
}
Run the app again and you will see something similar to that shown in Figure 2-30:
Figure 2-30 A view controller with title
Trang 7Now let's go and create a second view controller, without a xib file, and call it Second ViewController Follow the same process that you learnt in Recipe 2.7 Once you aredone creating this view controller, give it a title of Second Controller.
#import "SecondViewController.h"
@implementation SecondViewController
- (void)viewDidLoad{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"Second Controller";
}
Our plan is to push the second view controller on top of the first view controller 5
seconds after the first view controller appears on the screen so let's first import thesecond view controller in the first one:
Trang 8Figure 2-31 A view controller is pushed on top of another one
You can see that the navigation bar is displaying the title of the top view controller and
it even displays a back button which will take the user back to the previous view troller You can push as many view controllers as you would like into the stack and thenavigation controller will work the navigation bar to display the relevant back buttonswhich allow the user to back through your application's UI, all the way to the firstscreen
con-We learnt about pushing a view controller How about popping or removing a viewcontroller from the stack of the navigation controller? The answer is straightforward:
Trang 9using the popViewControllerAnimated: method of the navigation controller Let's makeour second view controller pop itself off of the stack automatically 5 seconds after it isdisplayed on the screen:
/* Get the current array of View Controllers */
NSArray *currentControllers = self.navigationController.viewControllers;
/* Create a mutable array out of this array */
NSMutableArray *newControllers = [NSMutableArray
Trang 10self.navigationController.viewControllers = newControllers
}
You can call this method inside any view controller in order to pop the last view troller from the hierarchy of the navigation controller associated with the current viewcontroller
con-Discussion
An instance of the UINavigationController class holds an array of UIViewControllerobjects After retrieving this array, you can manipulate it in any way that you wish Forinstance, you can remove a view controller from an arbitrary place in the array.Manipulating the view controllers of a navigation controller directly by assigning anarray to the viewControllers property of the navigation controller will commit the op-eration without a transition/animation If you wish this operation to be animated, usethe setViewControllers:animated: method of the UINavigationController class, asshown in the following snippet:
- (void) goBack{
/* Get the current array of View Controllers */
NSArray *currentControllers = self.navigationController.viewControllers;
/* Create a mutable array out of this array */
NSMutableArray *newControllers = [NSMutableArray
You want to display an image instead of text as the title of the current view controller
on the navigation controller
Solution
Use the titleView property of the view controller’s navigation item:
Trang 11/* Load an image Be careful, this image will be cached */
UIImage *image = [UIImage imageNamed:@"FullSizeLogo.png"];
The preceding code must be executed in a view controller that is placed
inside a navigation controller.
Discussion
The navigation item of every view controller can display a title for the view controller
to which it is assigned in two different ways:
• By displaying simple text
• By displaying a view
If you want to use text, you can use the title property of the navigation item However,
if you want more control over the title or if you simply want to display an image or anyother view up on the navigation bar, you can use the titleView property of the navi-gation item of a view controller You can assign any object that is a subclass of theUIView class In the example, we created an image view and assigned an image to it.Then we displayed it as the title of the current view controller on the navigation con-troller
2.11 Adding Buttons to Navigation Bars with UIBarButtonItem Problem
You want to add different buttons to a navigation bar
Trang 12Figure 2-32 Different buttons displayed on a navigation bar
You might be surprised that the bar on the bottom of Figure 2-32 is also a navigationbar! Navigation bars are of class UINavigationBar and can be created at any time andadded to any view So just look at all the different buttons with different shapes whichhave been added to the navigation bars in Figure 2-32 The ones on the top right have
a up and down arrow, the one on the top left has an arrow pointing to the left, the ones
Trang 13on the bottom navigation bar have all sorts of shapes We will have a look at creatingsome of these buttons in this recipe.
For this recipe, you must follow the instructions in Recipe 1.1 to create
an Empty application Then follow the instructions in Recipe 2.8 to add
a navigation controller to your app delegate.
In order to create a navigation button, we must:
1 Create an instance of UIBarButtonItem
2 Add that button to the navigation bar of a view controller using the view controller'snavigationItem property The navigationItem property allows us to interact withthe navigation bar This property has two properties on itself, namely rightBarBut tonItem and leftBarButtonItem Both these properties are of type UIBarButtonItem.Let's then have a look at an example where we add a button to the right side of ournavigation bar In this button we will display the text Add:
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"First Controller";
Trang 14Figure 2-33 A navigation button added to a navigation bar
That was simple and easy But if you are an iOS user, you probably have noticed thatthe system apps that come preconfigured on iOS have a different Add button Haveyou noticed that? Here is an example in the Alarm section of the Clock app on theIPhone Notice the + button on the top right of the navigation bar:
Trang 15Figure 2-34 The proper way of creating an Add button
It turns out, iOS SDK allows us to create system buttons on the navigation bar We do
that by using the initWithBarButtonSystemItem:target:action: initializer of the UIBar ButtonItem class:
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"First Controller";
Trang 16And the results are exactly what we were looking for:
Figure 2-35 A system Add button
The first parameter of the initWithBarButtonSystemItem:target:action: initializermethod of the navigation button can have any of the values listed in the UIBarButton SystemItem enumeration:
Trang 17- (void) switchIsChanged:(UISwitch *)paramSender{
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"First Controller";
Trang 18Figure 2-36 A switch added to a navigation bar
You can create pretty amazing navigation bar buttons Just take a look at what Applehas done with the up and down arrows on the top right corner of Figure 2-32 Let's dothe same thing, shall we?
Well it looks like the button is actually containing a segmented control (see ipe 2.6) So we should create a segmented control with two segments and add it to anavigation button and finally place the navigation button on the navigation bar Let'sget started:
Rec (void) segmentedControlTapped:(UISegmentedControl *)paramSender{
Trang 19
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"First Controller";
And this is how the output looks like:
Trang 20Figure 2-37 A segmented control inside a navigation button
The navigationItem of every view controller also has two very interesting methods:setRightBarButtonItem:animated:
Sets the navigation bar's right button but allows you to specify whether you wantthe placement to be animated or not Pass the value of YES to the animated parameter
if you want this placement to be animated
Trang 21If you use your iPhone as an alarm clock, then you certainly have seen a tab bar Have
a look at Figure 2-34 The bottom icons saying World Clock, Alarm, Stopwatch andTimer are parts of a tab bar The whole black bar at the bottom of the screen is a tabbar and the aforementioned items are tab bar items
A tab bar is a container controller In other words, we create instances of UITabBarCon troller and add them to the window of our application For each tab bar item, we add
a navigation controller or a view controller to the tab bar and those items will appear
as tab bar items A tab bar controller contains a tab bar of type UITabBar
So let's assume we have two view controllers with class names FirstViewControllerand SecondViewController We now go into our app delegate and define our view con-trollers and our tab bar:
#import <UIKit/UIKit.h>
@class FirstViewController;
@class SecondViewController;
Trang 22@interface Presenting_Multiple_View_Controllers_with_UITabBarControllerAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) FirstViewController *firstViewController;
@property (nonatomic, strong) SecondViewController *secondViewController;
@property (nonatomic, strong) UITabBarController *tabBarController;
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
Trang 23A tab bar, when displayed on the screen, will display tab bar items just like we saw in
Figure 2-34 The name of each one of these tab bar items comes from the title of theview controller that is representing that tab bar item so let's go ahead and set the titlefor both our view controllers
When a tab bar loads up, it only loads the view of the first view controller
in its items All other view controllers will be initialized but their views
won't be loaded This means, any code that you have written in the
viewDidLoad of the second view controller will not get executed until
after the user taps on the second tab bar item for the first time So if you
assign a title to the second view controller in its viewDidLoad and run
your app, you will realize that the title in the tab bar item is still empty.
For the first view controller we choose the title First:
Trang 24Now let's run our app and see what happens:
Figure 2-38 A very simple tab bar populated with two view controllers
Trang 25You can see that our view controllers do not have a navigation bar What should we
do? It's easy Remember that a UINavigationController is actually a subclass of UIView Controller So, we can add instances of navigation controller to a tab bar and insideeach navigation controller, we can load a view controller What are we waiting for then?Let's start with the header file of our app delegate:
#import <UIKit/UIKit.h>
@class FirstViewController;
@class SecondViewController;
@interface Presenting_Multiple_View_Controllers_with_UITabBarControllerAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) FirstViewController *firstViewController;
@property (nonatomic, strong)
UINavigationController *firstNavigationController;
@property (nonatomic, strong) SecondViewController *secondViewController;
@property (nonatomic, strong)
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
Trang 27Figure 2-39 A tab bar displaying view controllers inside navigation controllers
As we can see in Figure 2-34, each tab bar item can have text and an image We've learntthe using the title property of a view controller, we can specify this text but what aboutthe image? It turns out every view controller has a property called tabItem This property
is the tab item for the current view controller and you can use this property to set theimage of the tab bar item, through the image property of the tab item I've alreadydesigned two images One a rectangle and one a circle and I'm going to display them
as the tab bar item image for each of my view controllers Here is for the first viewcontroller:
Trang 29Figure 2-40 Tab bar items with images
See Also
XXX
Trang 302.13 Displaying Static Text with UILabel
Trang 31Figure 2-41 Labels as titles of each one of the settings
You can see that the labels are displaying text in the Settings app, such as General,iCloud, Twitter, Phone, FaceTime and etc To create a label, we instantiate an object
of type UILabel Setting or getting the text of a label can be done through its textproperty So let's define a label in our view controller's header file:
Trang 32self.view.backgroundColor = [UIColor whiteColor];
CGRect labelFrame = CGRectMake(0.0f,
0.0f,
100.0f,
23.0f);
self.myLabel = [[UILabel alloc] initWithFrame:labelFrame];
self.myLabel.text = @"iOS 5 Programming Cookbook";
self.myLabel.font = [UIFont boldSystemFontOfSize:14.0f];
Trang 33Figure 2-42 A label that is too small in width to contain its contents
You can see that the contents of the label are truncated with trailing full stops becausethe width of the label isn't enough to contain the whole contents One solution would
be to make the width longer but how about the height? What if we wanted the text towrap to the next line? Ok, go ahead and change the height from 23.0f to 50.0f:
CGRect labelFrame = CGRectMake(0.0f,
0.0f,
100.0f,
50.0f);
Trang 34If you run your app now, you will get exactly the same results that you got in ure 2-42 But you might ask, I increased the height, why didn't the content wrap to thenext line? It turns out that UILabel class has a property called numberOfLines that needs
Fig-to be adjusted Fig-to the numeber of lines the label has Fig-to wrap the text Fig-to, in case it runsout of horizontal space If you set this value to 3, it tells the label that you want the text
to wrap to three lines if it cannot fit the text into one line:
self.myLabel.numberOfLines = 3;
If you run the app now, you will get the desired results:
Figure 2-43 A label wrapping its contents to 3 lines
Trang 35In some situations, you might not know how many lines is required to
display a certain text in a label In those instances, you need to set the
numberOfLines property of your label to 0.
If you want your label's frame to stay static and you want the font inside your label toadjust itself to fit into the boundaries of the label, then you need to set the adjustsFont SizeToFitWidth property of your label to YES For instance, if the height of our label was
to be 23.0f as we say in Figure 2-42, we could adjust the font of the label to fit into theboundaries Here is how it works:
- (void)viewDidLoad{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
CGRect labelFrame = CGRectMake(0.0f,
self.myLabel.text = @"iOS 5 Programming Cookbook";
self.myLabel.font = [UIFont boldSystemFontOfSize:14.0f];
Trang 36Figure 2-44 Username and Password text fields allowing text entry
A text field allows only 1 line of text to be input/displayed as a result,
the default height of a text field is only 31 points In Interface Builder,
this height cannot be modified but if you are creating your text field in
code, you can change the text field's height, although this will not change
the number of lines you can render in a text field, which is 1.
Let's start with the header file of our view controller to define our text field:
Trang 37This is followed by synthesizing the myTextField property:
self.view.backgroundColor = [UIColor whiteColor];
CGRect textFieldFrame = CGRectMake(0.0f,
Trang 38Figure 2-45 A simple text field with center aligned text
In order to create this text field, we used various properties of UITextField These are:borderStyle
This property is of type UITextBorderStyle and it specifies how the text field shouldrender its borders
contentVerticalAlignment
This value is of type UIControlContentVerticalAlignment and it tells the text fieldhow the text should appear, vertically, in the boundaries of the control If we didn't
Trang 39center the text vertically, it would appear on the top left corner of the text field bydefault.
textAlignment
This property is of type UITextAlignment and it specifies the horizontal alignment
of the text in a text field In this example, we have centered the text horizontally(as well as vertically)
text
This is a readwrite property You can either read from it or write to it Readingfrom it will return the text field's current text and writing to it will set the text field'stext to the value that you specify
A text field sends delegate messages to its delegate object These messages get sent, forinstance, when the user starts editing the text inside a text field or when the user finishesediting or when the user enters any character in the text field To get notified of theseevents, we need to set the delegate property of the text field to our object The delegate
of a text field must conform to the UITextFieldDelegate protocol so let's first take care
textFieldShouldBeginEditing:
A method that returns a BOOL telling the text field (the parameter to this method)whether that text field should start getting edited by the user or not Return NO ifyou don't want the user to edit your text field
Trang 40changed If you return NO, the change in the text of the text field will not be
con-firmed and will not happen
textFieldShouldClear:
Each text field has a clear button which is usually a circular X button When the
user presses this button, the contents of the text field will automatically get erased
We need to manually enable the clear button though If you have enabled the clearbutton and you return NO method, that gives the user the impression that your appisn't working so make sure you know what you are doing because the user sees aclear button, presses it but never sees the text in the text field get erased
textFieldShouldReturn:
This method gets called when the user has pressed the Return/Enter key on thekeyboard, trying to dismiss the keyboard You should resign the text field as thefirst responder in this method
Let's mix this recipe with Recipe 2.13 and create a label under our text field and displaythe total number of characters entered in our text field, in the label Let's start with ourheader file:
#import <UIKit/UIKit.h>
@interface Accepting_User_Text_Input_with_UITextFieldViewController
: UIViewController <UITextFieldDelegate>
@property (nonatomic, strong) UITextField *myTextField;
@property (nonatomic, strong) UILabel *labelCounter;
- (void) calculateAndDisplayTextFieldLengthWithText:(NSString *)paramText{
self.labelCounter.text = [NSString stringWithFormat:@"%lu %@",
(unsigned long)[paramText length],