Now it’ time for something more advanced. In Interface Builder how-to I told you, that I.B. is great for designing interfaces, but there are cases this knowledge – creating everything programmatically will be necessary and helpful, like:
- there is an unknown number of object which will be added
- the number of object is static but enormous, and they are almost the same with tiny differences
- you want to be better than others and you like hard not-needed extra work…
Let’s start. So far you created everything in Interface Builder, you were editing NIB (.xib) files, but in fact Interface Builder created the whole code for you in the background.
As I mention in article about I.B. I told you, that you can create the Interface only in I.B., partialy in I.B. and Xcode or only in Xcode.
I personally advice you to use Interface Builder wherever possible using Xcode when necessary, if some properties cannot be set in I.B.. In this article I will show you how to create everything using only Xcode. Let’s start.
Whenever you created any object to be visible in Interface Builder you used the keyword IBOutlet for example: IBOutlet UILabel *myLabel;. If you customize in this case myLabel in Xcode only, you can skip this keyword, so: UILabel *myLabel;. The same with any methods / actions, you were using IBAction what in fact is an equivalent to void (no value returned), but IBAction gives you one advantage – that it’s visible in I.B.. So if are impementing a method that will be called by objects created only in Xcode you can use: -(void)myAction; instead of -(IBAction)myAction; and of course if you need to know what object called the method: -(void)myAction:(id)sender instead of -(IBAction)myAction:(id)sender.
Creating a view programmaticaly
Let’s start by creating programmaticaly a view. Let’s add a UIViewController class, name it MyView.m (and MyView.h). In you AppDelegate’s header add standard lines:
#import "MyView.h" @class MyView;
and in AppDelegate’s implementation:
MyView *viewController = [MyView alloc]; [window addSubview:viewController.view];
Now go to MyView.m, and find somewhere the commented loadView method, it should look like:
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
Deleate /* and */ to activate this method. During allocating of this class (or any UIViewController) the loadView will be automatically called to load the view (and BTW, once view is loaded viewDidLoad is called). Extend loadView class by these two lines:
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; self.view.backgroundColor = [UIColor yellowColor];
If you Build and Go you will get the empty yellow
screen (with status bar of course).
Why?
It’s simple. first line is creating a new view [UIView alloc]. Because MyView class is UIViewController it already expects a view. So far, you created a view in Interface Builder connecting view outlet to view’s preview, if I can call it like this, this time you created it programmatically. The second part is creating the view’s frame, you are setting the coordinates and size of view. Quick info about CGRectMakes’s arguments:
CGRectMakes(xTopLeftCorner,yTopLeftCorner,width,height)
The 2nd line is quite obvious, just changing the background color. Hmm, but where did you put anything to make this view visible? Answer: in AppDelegate implementation file. So, to be more specific, visit your …AppDelegate.m file:
- MyView *viewController = [MyView alloc] is creating new object of class MyView and automatically calls loadView method, so you don’t have to
- [window addSubview:viewController.view] is adding the view created by loadView to the application window
Hope it’s clear now.
Adding a label programmatically
Add this block of code to loadView or viewDidLoad method:
UILabel *myLabel2 = [[UILabel alloc] initWithFrame:CGRectMake(50, 200, 200, 80)]; myLabel2.text = @"only Xcode"; myLabel2.textAlignment = UITextAlignmentCenter; myLabel2.textColor = [UIColor yellowColor]; myLabel2.shadowColor = [UIColor whiteColor]; myLabel2.shadowOffset = CGSizeMake(1,1); myLabel2.font = [UIFont fontWithName:@"Zapfino" size:20]; myLabel2.backgroundColor = [UIColor greenColor]; [self.view addSubview:myLabel2]; [myLabel2 release];
Code is similar to that one, where you created the view. Differences? [UILabel alloc], not [UIView alloc] and another frame which suits me. Next 7 lines is a customization of label – changing label’s text, text alignment, text color, shadow, font, also background color. To show label on view you use [self.view addSubview:myLabel2];. I’ve already told you once, but I will repeat, almost everything visible on iPhone / iPod touch is some kind of view. UILabel is also UIView’s subclass.
The last line contains: [myLabel2 release]; it frees our memory, but use it wisely. This time I didn’t put it into dealloc method that is called when application terminates. Hmmm… no…, read the article about Memory management and you will see the point.
Now your app should look like this:
You can easily add next label, remember to give it an unique name:
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 200, 80)]; myLabel.text = @"Isn't it amazing?"; myLabel.textAlignment = UITextAlignmentCenter; myLabel.backgroundColor = [UIColor colorWithRed:0.2 green:0.9 blue:0.5 alpha:0.3]; [self.view addSubview:myLabel];
Creating a button programmaticaly
Let’s start with the code:
myButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] initWithFrame:CGRectMake(50, 300, 200, 80) ]; [myButton setTitle:@"And a button" forState:UIControlStateNormal]; [myButton setTitle:@"Alert" forState:UIControlEventTouchDown]; [myButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; myButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; myButton.backgroundColor = [UIColor clearColor]; [myButton addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:myButton];
As you see above, this time I didn’t use something like [UIButton alloc], but [UIButton buttonWithType:...]. Why? Because I had to, if the button was simply an image I would use alloc, but as long as I want to use the predefined type I had to create it using above command.
Now you might ask a question why I set some properties using [myObject something:], and others using myObject.something=. Answer: some properties can be set using both of these two ways, some only using one. For example in UILabel:
myLabel.text = @"asdfg"; [myLabel setText:@"asdfg"];
are the equivalents. So comming back to my button, I set two different titles, one is displayed during normal state of button, and the other while it’s being pressed, next color, alignment, backgroundColor. Later I connected an action to the button – in bold is a name of method called when user will TouchUpInside – press the button. All you need to do is to implement the buttonAction method:
-(void)buttonAction { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Hmmm" message:@"It really works" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil]; [alert show]; [alert release]; }
If you would like to have info about what object called the method [(id)sender], add a colon on the end of class name in adding a selector to the button:
[myButton addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
And of course:
-(void)buttonAction:(id)sender {
//...
}
One thing you have to know
When you set a frame using CGRectMakes(TopLeftX,TopLeftY,width,height), or the center using CGPointMake(CenterX,CenterY), you need to know something more. These two x, y coordinates of top left corner or center point, are set according to the view (or it subclass) that our object is subview of . So let’s say you have a view 320×480px, but it is not placed in the center of the screen (window), it’s a little bit to the left. If you add a UILabel as the view’s subview and set the center property of that label equal CGPointMake(160,240), it will be in the exact center of the view, but together with the view moved a little bit to the left.
Conclusion
As you see, designing an interface strictly in Xcode is a little bit tiring, but there will be cases you will have to use it in practise. The difficult maybe the lack of knowledge what property customize some key and less importan parts of given object. Everything can be find in documentation. You can also get a list of all available properties pressing Esc-key after “myObject.” or “[myObject “.
As usuall I prepared a project for you, so if something doesn’t work for you, compare it with mine.


