Posts Tagged ‘Xcode’

Creating a view programmatically

April 29th, 2009

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 yellowyellowview 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:

yellowviewlabel

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 :D " 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.

noibend

xcodeproj

Download the project

Hello World

April 25th, 2009

Hello World – usually the first program every programmer, no matter in what programming language, creates. It’s very simple and a great example if I present it to you step by step.

Let’s start by opening Xcode. Close any welcome windows which may appear. Choose File => New Project.

xcode_template

Make sure the Application from iPhone OS category is selected on the left and choose Window-Based Application and press Choose… . [ Window-Based Application is the simplest template you can choose to begin, other are more complex but can save your time if they suit your application ]. Save your project wherever you like and name it properly for example HelloWorld.

helloworld_start

Xcode created some main files already for you. These files are categorized into 5 groups:

  • Classes – where HelloWorldAppDelegate.h (header) and .m (implementation) are. In header file you have declaration of the class, it’s objects, frameworks and other files inclusion. In implementation file you have class methods.
  • Other SourcesHelloWorld_Prefix.pch is the prefix header for all other source files within your project, so if in future you need to import the same file to all other classes you can use this file instead of modifying each of the classes. main.m is the standard main() function known from C language that is called first.
  • ResourcesMainWindow.xib is called NIB file (like other with .xib extension) to create user interface with Interface Builder. Info.plist is the configuration file, where you can change some project settings – Bundle name and so on.
  • Frameworks – source files created by Apple providing you basic and major functionality.
  • Products – compiled project goes there

Sounds difficult? I don’t think so. You can organize you files in a way that suits you. You will modify only files from Classes and create other classes.

To create the simplest Hello World example we could just edit a MainWindow.xib with Interface Builder but you wouldn’t learn anything at all. We are going to create your own view (iPhone application consists of only one window any many views displayed in window) and its view controller.

In Xcode choose File => New File and from Cocoa Touch Classes select UIViewController subclass, Next. Enter MyView.m, as file name, and without changing anything else press Finish.

viewcontrollernewfileviewcontr

Now let’s create a view, where the text will be displayed. Choose File => New File and from User Interfaces choose View XIB, Next, call it MyView.xib, Finish.

Double click MyView.xib and it will be opened in Interface Builder.

interfacebuildermainview

As you see MyView.xib currently consist of three objects. File’s Owner – there we will assign our MyView class soon, First Responder – handler of touches, buttons pressing, entering data, and View the part that in next few minutes will be visible on simulator screen.

In Interface Builder go to Tools => Library. Find on the list Label (UILabel) and drag and drop it on the View. Click on the label and resize it. Double click and change it text to Hello World. You can also go to Tools => Inspector and change it aligment, color, shadow – it’s up to you, don’t close the Inspector window.

Now select File’s Owner and go to the last tab in Inspector (Object Identity). View won’t be shown by itself that is why we already prepared the MyView class that’s going to control the view; under Class Identity in Inspector enter MyView as Class. As you see auto-completion works great (also in Xcode) so just entering m refers to MyView. Now File’s Owner is a type of MyView, not NSObject any longer. That’s not all. One .xib file may consists of many views and even if you have only one right now, you have to set is as a main view of MyView class. Again in File’s Owner’s Inspector in second tab (MyView connections) you have 3 outlets, one of them is called view.

interfacebuildernoconnection

Click on the circle that’s on the right next to view hold your mouse button and drop it on the View window or View from MyView.xib window. The connection is set. While using an Interface Builder you have no options to give a unique names of objects like views, labels, switches, buttons or any other part of the interface. You have to prepare them in your class files like MyView.h and .m, and later you connect them just like before. Because MyView class is a UIViewController it already expects a view you can create programmaticaly or using Interface Builder.

interfacemyviewconnections

Let’s choose File => Save and go back to Xcode. Now we have to create some code. MyView class is already prepared to display Hello World, but we have nowhere entered any information to call this class. Let’s fix it.

Go to HelloWorldAppDelegate.h and under:

#import <UIKit/UIKit.h>

enter:

#import "MyView.h"
@class MyView;

These two lines of code allows you to use MyView class within HelloWorldAppDelegate.h and .h – files that are called when the application start. Let’s now go to the implementation file – HelloWorldAppDelegate.m and in the applicationDidFinishLaunching method enter these two lines:

MyView *viewController = [[MyView alloc] initWithNibName:@"MyView" bundle:[NSBundle mainBundle]];
[window addSubview:[viewController view]];

it should look like below:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
	MyView *viewController = [[MyView alloc] initWithNibName:@"MyView" bundle:[NSBundle mainBundle]];
	[window addSubview:[viewController view]];
   	// Override point for customization after application launch
	[window makeKeyAndVisible];
}

First line creates the new MyView objects, we will use only one instance of it, but in some cases we can create (alloc) more objects from the same class. The second file put the MyView class view on the application window, in other words the view is a subview of a window. Everything what is part of the interface is a kind of view. The label with HelloWorld is a subview of MyView’s view.

That’s all. Let’s press Build & Run. In the iPhone Simulator we should see our application.

helloworldsimulator

That was to simple, wasn’t it? So, I would like to show you how to handle actions, like pressing a button. When the button is pressed the label shows Hello Universe.

Let’s go to the MyView.h and between { and } let’s add an label outlet and before @end an action. The outlet looks like: IBOutlet UILabel *myText that’s mean that my name of the object is myText of type UILabel, IBOutlet keyword means that it’s visible in Interface Builder. The action looks like -(IBAction)changeText; – I declare an action – method named changeText which will be visible in Interface Builder because of IBAction keyword. If you compile (Build) your project now, you will get two warnings, because in header file you declare the changeText but in implementation file doesn’t provide any code what this method does.

MyView.h should look like:

#import <UIKit/UIKit.h>
@interface MyView : UIViewController {
	IBOutlet UILabel *myText;
}
-(IBAction)changeText;
@end

Now we have to implement changeText method in MyView.m file. Add this code below @implementation MyView:

-(IBAction)changeText {
	myText.text = [NSString stringWithFormat:@"Hello Universe"];
}

As you see, we change the text of the label by using it’s name myText and and text keyword – property with dot between them, why not only myText? That’s because myText is the bigger object not only a text placeholder, you can easily change it’s background colour, font, opacity, shadows, just like you could in Interface Builder.

Build your project, it’s everything from the code site, now we have to go back to improve an interface. If you have already quited Interface Builder double click MyView.xib to reopen it. From the library, select Round Rect Button (UIButton) and drag’n'drop it to the view. Just like with the label you can double click on it and enter some text, for example Change Text. Let’s go to the File’s Owner Connections Inspector and you should see MyText as one of the outlets, and changeText as one of the actions:

connections

Just in the same way you connected view outlet to your view, connect myText to the label – click on the circle next to myText and release your button on the Hello World label. Although it’s only one label on the view, you are doing it to show the compiler what/where is the label called myText. Now let’s connect an action with the button. Click on the circle next to changeText and release your mouse button on the Change Text button. The menu should appear.

buttonactions

As you see there are few predicted user behaviours how he can press the button. We are interested in Touch Up Inside – it will call the changeText method when user press and release his finger without draging it out from the button. Now, MyView Connections should look like:

connectionsall

Save MyView.xib and press Build and Go. Now pressing the Change Text button changes the label’s text from Hello World to Hello Universe. Pressing the button again calls the changeText method but there is no change visual to us. It’s almost all but we forgot about one thing, so called Memory Management. We declared myText outlet and it will stay in memory until user reboot the device. You need to fix it – go to the dealloc method in MyView.m (should be on the bottom) and add a line [myText release];.

- (void)dealloc {
    [super dealloc];
    [myText release];
}

That’s all. Hello World is something you should do all by yourself from now. I tried to show you everything as simple as possible. In next examples I will not tell you everything so detailed and post screenshots for every single step.

xcodeprojDownload the project

Xcode

April 24th, 2009

xcode

dev_xcodemediumXcode is the main tool you will use during your apps development. It has a variety of settings and can be customized in the way it suits you, but it’s not as difficult it appears to be.

The difficult may be the code, programming language you will enter to write your application. Xcode is not only used to built iPhone apps but as well for Mac and other environments.

As you see on the Xcode screenshot above, its window has 3 major parts.

  1. Toolbar
    1. Active Target
      Here you can choose what is the active target. In most cases there will be only one position. Targets are useful if you won’t to create two similar version of your application, full and lite for example, although for beginners it’s much easier to create a new copy of the project for each version.
    2. Active SDK
      Here you can select for which environment and firmware version you are going to compile your application. It’s the best to compile for the lowest possible version. If you want to debug your application on iPhone Simulator choose Simulator – iPhone [version], if run on real device, choose Device – iPhone [version]. To run your code on iPhone using official way you have to be an iPhone Developer (and pay $99).
    3. Active Build Configuration
      Choose Debug for simulator, Release for real device and Distribution (will be available later) to send it later to App Store.
    4. Action
      Never mind, most of this option are available in ctrl-click menus.
    5. Build & Build and Go
      Compiles (and runs) your application.
    6. Tasks
      Terminates / kills application.
    7. Info
      Never mind.
    8. Editor
      Never mind.
    9. Search
      Ask your brother.
  2. Left part of the window
    When you create a new project, Xcode makes many files for you, so it saves your time because the main part of your application usually is the same. As you see files in project are organized into folders (groups), by default: Classes, Other Sources, Resources,Frameworks and Products. You can organize it in a way you like. I will explain what each file does in one of next lessons.
  3. Right part of the window
    Right part is divided into two sub-parts. Upper part shows the list of contents in selected folder / group / project / framework. Lower part displays a place where finally you can put some code.

That’s all. Not so difficult I guess.