Step 1: Read the Hello World tutorial
If you are are unfamiliar with developing in Objective C and IPhone SDK please take a moment to go through the earlier tutorial IPhone SDK Hello World. It also contains instructio ns on how to install XCode and the IPhone SDK.
Step 2: Create a project
Select File > New Project or Apple Key + Shft + N to bring up the new project menu. Select the Applications item of the IPhone OS section from the menu on the left, and select Window Based Application from the icons on the right. When prompted enter a project name, I have used TabBar in the sample code. You should have two files TabBarAppDelegate.h and TabBarAppDelegate.m.
Step 3: Create the View Controllers
We are going to create two tabs and we need a view controller for each one. Hence Create two files of type UIViewController SubClass. I named the files View1Controller.m and View2Controller.m Make sure you check the box to also create the header file.
Now You should have Six files in your project:
TabBarAppDelegate.m
TabBarAppDelegate.h
View1Controller.m
View1Controller.h
View2Controller.m
View3Controller.h
Step 4: Setup the View Controllers
View1Controller
First we will setup the view containing the Button and Text Field. Browse to the View1Controller.h header file and add the following interface elements, UITextField, UIButton, UIView and also add a reference to the Application delegate which will be used to communincate between views. We also create properties for each of the variables we have defined. The final code should look something like this:1 #import <UIKit/UIKit.h>
2 #import "TabBarAppDelegate.h"
@class TabBarAppDelegate;
2 @interface View1Controller : UIViewController
3 {
4 UITextField *textField;
5 UIButton *cmdButton;
6 UIView *myView;
7 TabBarAppDelegate *delegateRef;
8 }
9
10 @property (nonatomic, assign) UITextField *textField;
11 @property (nonatomic, assign) UIButton *cmdButton;
12 @property (nonatomic, assign) UIView *myView;
13 @property (nonatomic, assign) TabBarAppDelegate *delegateRef;
14
15 @end
1 - (id)init
2 {
3 if (self = [super init])
4 {
5 // Initialization code
6 self.title = @"Text and Button"; //Set View title which will be displayed in Tab Bar
7 // create and configure the view
8 CGRect cgRct = CGRectMake(0.0, 0.0, 480, 320); //define size and position of view
9 myView = [[UIView alloc] initWithFrame:cgRct]; //initilize the view
10 myView.autoresizesSubviews = YES; //allow it to tweak size of elements in view
11 self.view = myView; //set view property ov controller to the newly created view
12
13 // create a UIButton (UIButtonTypeRoundedRect)
14 cmdButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
15 cmdButton.frame = CGRectMake(100, 100, 100, 50);
16 [cmdButton setTitle:@"Click Me" forState:UIControlStateNormal];
17 cmdButton.backgroundColor = [UIColor clearColor];
18 [cmdButton addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
19 cmdButton.adjustsImageWhenHighlighted = YES;
20
21 //create a text field
22 cgRct = CGRectMake(60, 170, 200, 50); //define size and position of textbox
23 textField = [[UITextField alloc] initWithFrame:cgRct];
24 textField.text = @"Enter Text Here";
25 textField.borderStyle = UITextBorderStyleBezel;
26
27 //Add text field and button to main view
28 [self.view addSubview:cmdButton];
29 [self.view addSubview:textField];
30 }
31 return self;
32 }
Also we need to add an action handler to take care of the button click. Add the following method to View1Controller.m. Note that view are accessing the label using the view controller that we reference using the AppDelegate instance pointed to by the delegateRef property.
1 - (void)action:(id)sender
2 {
3 [self.textField resignFirstResponder]; //Hide Keyboard
4 self.delegateRef.view2Controller.label.text = self.textField.text;//Ubdate label
5 }
View2Controller
On tot he second view controller, we do not keep an app delegate instance here because this view does not need to initiate any interaction with the first view. If this were not the case then we would also keep a reference here
1 #import <UIKit/UIKit.h>
2 @interface View2Controller : UIViewController
3 {
4 UILabel *label;
5 UIView *myView;
6 }
7
8 @property (nonatomic, assign) UILabel *label;
9 @property (nonatomic, assign) UIView *myView;
10
11 @end
In the View2Controller.m file synthesize the properties and write and init method to create the user interface elements.
Step 5: Setting Up the App Delegate
In the TabBarAppDelegate.h header file we define instances of the UITabBarController as well as the two views we have just setup. We create properties for these variables an also declare he relevent classes and import the relevent header files. The final code should look something like this:
2 #import "View1Controller.h"
3 #import "View2Controller.h"
4 @class TabBarViewController;
5 @class View1Controller;
6 @class View2Controller;
7 @interface TabBarAppDelegate : NSObject <UIApplicationDelegate>
8 {
9 UIWindow *window;
10 UITabBarController *tabBarController;
11 View1Controller *view1Controller;
12 View2Controller *view2Controller;
13 }
14
15 @property (nonatomic, assign) UIWindow *window;
16 @property (nonatomic, assign) UITabBarController *tabBarController;
17 @property (nonatomic, assign) View1Controller *view1Controller;
18 @property (nonatomic, assign) View2Controller *view2Controller;
19 @end
In the implementtion file TabBarAppDelegate.m update the applicationDidFinishLaunching method to create the view controllers and the tab bar controllers and add them to the window. The code for this is as follows.
1 @synthesize window;
2 @synthesize view1Controller;
3 @synthesize view2Controller;
4 @synthesize tabBarController;
5 - (void)applicationDidFinishLaunching:(UIApplication *)application
6 {
7 //Initilize objects
8 tabBarController = [[UITabBarController alloc] init];
9 view1Controller = [[View1Controller alloc] init];
10 view2Controller = [[View2Controller alloc] init];
11
12 //Add a refernce to self in the View1Controller so that it can reference View2Controller via this object
13 view1Controller.delegateRef = self;
14
15 //Add views to the TabBar
16 tabBarController.viewControllers = [NSArray arrayWithObjects:view1Controller, view2Controller, nil];
17
18 //Add tabbar to window and display
19 [window addSubview:tabBarController.view];
20 [window makeKeyAndVisible];
21 }
Step 6: Build and Go
Click the Build an Go button to run your code and you should see the Tab Bar with the first view Loaded. Enter your teck and click the button on the screen. Now load the seconf view by clicking the right Tab and see your text updated there.
Step 7: Extra Credit Adding Icons
Create two 32 x 32, 150 dpi, grey scale png images that you want to use as icons I called mine icon.png and icon1.png. Import the images into the resources folder by right clicking it and selecting Add > Existing Files... and selecting the image files. Now in the init method of both ViewControllers (View1Controller and View2Controller) add the following lines respectively.
self.tabBarItem.image = [UIImage imageNamed:@"icon.png"];
self.tabBarItem.image = [UIImage imageNamed:@"icon1.png"];
Click Build and Go to see the icons.
Concluding Note
I hope this tutorial was clear and helpful let me know if there are any problems or if it can be improved. Also please download the XCode project source from my site Here











Josh S
Invite as author
PNG file
Ok I have a few questions about these icons.
I'm a graphic designer and I don't want to keep sending files to the programmer to compile for me to look at only for them to look totally shit. I have sent so many already :/ I just cant get it right.
How do I make a nice looking circle if I can only use solid pixles,
every thing looks Jaged, (not like the head in the facebook app)
If I make a circle in illustrator then past that into photoshop on a 32X32 RGB file
then the circle comes through with a heap of nice anti aliasing so that the cirle looks smooth.
I have a transparent background layer.(photoshop checkerboard)
I save as 8bit 16 color PNG
but then the iphone compiler turns all the anti Aliasing into solid which looks nasty.
What would happen if I created a a solid black png then did a nice anti aliased Alpha Channel and saved it as a 24 bit PNG?
Whould that work?
If not then how do you create nice smooth icons?
thanks so much every one :)
J
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
my email is uismail@uwaterloo.ca
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
Ok I have figured it out.
Basicly you have to not use solid greys, always use black but make the pixels that you want as anti aliasing slightly transparent, to do this in photo shop simply make a new layer, draw solid black pixels then make that layer slightly transparent. so if you put a lower layer solid white you will see that the slight transparent layers look Grey, but they aren't they are slightly transparent black.
I found a great online thing that lets you convert PNG in bedded in aps so you can se how they are made.
(remember to turn off the white layer and save it as 24 bit PNG with transparency ticked., Use "save for web" in photoshop)
to do it find the app that you want to rip in itunes, right click , show in windows explorer, (not sure of the mac equivalent) once the finder or explorer window opens copy the app.ipa file to the desktop,
now on the new copy of the app on the desktop change the extension from
.ipa to .zip
Now open the zip file and fin the png you want to have a look at.
then go to
http://zope.release7
and use it to convert your unreadable PNG to a readable one :)
As for my alpha question above, it doesn't work. so forget the alpha channel in photoshop.
Have fun
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
zwirdsch
Invite as author
Question to -(id)init
I've implemented an init-Method in my own application but it never gets called. I thought a init method get called always when the application is started and it is used for initialising tasks. Is this wrong?
Thanks for your help!
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
zwirdsch
Invite as author
Disadvantages of using Interface Builder
Because all the Apple Iphone Guides encourage you to use the IB.
2. Regarding your init(id) method in your View1Controller class: The way you set up the view in this method, don't you run the risk of using to much memory? Or to consume too much resources?
I'm asking because you're writing yourself that it isn't the best solution.
2: I suppose we are using more memory in the sense that the elements are allocated before being needed. However all elements will be loaded and therefore the max memory used is the same, only on this code the max memory is used for a longer period of time. (Time between the first view being loaded and the second view being loaded for the first time). If you really needed memory you could deallocate and reallocate elements each time they are needed. In comparison to that case my approach uses twice the memory. Its up to you how much complexity you are willing to add to save memory.
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
zivelli
Invite as author
Assign vs Retain
Thanks for providing this great resource to the iPhone community!
I do have one question concerning the use of assign instead of retain for the TabBarAppDelegate.
Most of the examples in the SDK use Retain for the properties and I don't really understand your explanation.
How do you decide which one to use and what are the implications with regards to memory leaks?
Thanks again.
assign is just a shallow copy i.e. it points to the same object.
if you want to have multiple classes access the same object we need a shallow copy so we are always pointing to the same object otherwise each class will have its own copy not the actual one that is displayed.
let me know if this is clear otherwise I will go into greater detail.
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
For instance in the UICatalog example, the main table, UITableView uses Retain, so would subsequent calls by other classes invoke a new object and not, as you say, point to the same object.
Reading through many of the examples provided by Apple the rules as you stated don't really seem to apply. Even the DrillDownSave example uses Retain and not assign for the different controllers?
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
"Keep in mind retain and assign are basically interchangeable when garbage collection is enabled."
http://theocacao.com
I am going to correct this as soon as I get time
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
The copy attribute is roughly equivalent to C++'s copy, or Java's clone.
See Apple's property attribute documentation for details: http://developer.app
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
Joseph Dearman
Invite as author
Interface Builder?
This tutorial is exactly what I needed to get deeper into tabbars! I have one newbie question; How can I use interface builder to create the UI? I've tried about everything I can think of and am starting to feel a little dumb. Thanks!
http://www.iphonesdk
Just a word of warning do not rely on the interface builder in all but the most basic applications it tends to make things harder to manage.
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window
warpedspeed
Invite as author
Question about the hand off
Both Controller objects remain live (in memory) after the first time the respective view is displayed, Each controller is a delegate for a different view so only the one corresponding to the view currently displayed can receive events from the UI. However as the other controller is still in memory if the programmer has a reference to it (s)he can call methods or change value of fields. These will obviously not change the interface until that view is loaded again. Let me know if this answers your question.
EditSaveCancelDeleteDeleteBlock this userReport abusive commentHide report window