Archive for the ‘Dev Center’ category

Timers

April 27th, 2009

Timers – believe me or not, but they are useful not only in programming stopwatches.

Let’s give some examples.

  • To show a welcome screen and to close it after several seconds
  • You are making a game and you would like to display an info how long user is playing current stage, without comparing NSDate (start and current).
  • To create an animation without fade in / fade out effect.

Using timer (NSTimer) you are able to launch any task after given time or repeat it periodically.

I will give you an description with code for each of above examples.

Welcome screen

Welcome screen is shown only once during launch so there is no need to create any information in header file of your class about NSTimer. All you need to do is to add this line to your viewDidLoad method:

	[NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(closeWelcomeScreen) userInfo:nil repeats:NO];
And to develop a closeWelcomeScreen method:
-(void)closeWelcomeScreen {
	[welcomeScreen removeFromSuperview];
}
closeWelcomeScreen will be called in 1.5 seconds after view was loaded. Remember to set the repeats property to NO this time. If you set YES, the method closeWelcomeScreen would be called every 1.5 seconds.
Right now we are simply removing the welcomeScreen, of course it’s up to you if you decide to perform an animation to change it’s alpha property it or to add something on top of welcomeScreen.

How long?

Now we will create a timer that will call the method every 0.01 second. In header file we need to add a float variable (float time;) and it’s also a label to show somewhere the value of this variable:

@interface MyView : UIViewController {
	IBOutlet UILabel *myLabel;
	float time;
}

Now in viewDidLoad or any other method you will call by yourself, add:

	[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(countTime) userInfo:nil repeats:YES];

And you need to implement countTime method:

-(void)countTime {
	time += 0.01;
	myLabel.text = [NSString stringWithFormat:@"%.2f",time];
}

As you see, this time NSTimer’s repeats property is set to YES, and that’s why it will call countTime method every 0.01 second.

Animations using NSTimer

As I told you before using typical animations (and transformations) ([UIView beginAnimations:nil context:NULL] and [UIView commitAnimations]) you get the nice fade in and out effect. To perform a rotation for example you have to create a similar timer like in code above, with tiny difference. It won’t be changing label’s text but transforming it using each time bigger angle.

	[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(countTime) userInfo:nil repeats:YES];
-(void)countTime {
	rotation += 0.001;
	myLabel.transform = CGAffineTransformMakeRotation(M_PI*rotation);
} 

Remember to add in your header file rotation variable: float rotation;

Stoping NSTimer

In each of above examples when NSTimer repeats itself you can’t stop it – the time will grow and/or your object will be rotated. To obtain it you have to add the NSTimer object to the header and later in implementation to use it’s invalidate method whenever/wherever you want to stop it. Below I show you an example of the timer that will make a full rotation of myLabel and invaliate itself.

Header:

@interface MyView : UIViewController {
	IBOutlet UILabel *myLabel;
	float rotation;
	NSTimer *rotationTimer;
}

Starting the timer:

	rotationTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(rotate) userInfo:nil repeats:YES];
And the rotate method:
-(void)rotate {
	if (rotation >= 2.0) {
		[rotationTimer invalidate];
		return;
	}
	rotation += 0.001;
	myLabel.transform = CGAffineTransformMakeRotation(M_PI*rotation);
}
You can call invalidate method anywhere in your project. A button can invalidate your timer or the timer itself as shown above.

Personal experience

Timers can be more complex than just counting a time or perform a simple task. If you use timer as a run loop of your game for example, be careful. If many methods can invalidate the timer you should check if it cannot be invalidated twice sometimes. It will crash your application. Although NSTimer has the boolean method isValid, once NSTimer is invalidated you can’t use this property. Declaring any NSTimer I also add the boolean variable with similar name:

NSTimer *myTimer;
bool myTimerInvalidated;

Each time I start the timer I set the boolean equals NO, each time I want to invalidate the timer I use:

if (!myTimerInvalidated) {
	myTimerInvalidated = YES;
	[myTimer invalidate];
}

Download the sample project to see live example of NSTimers.

xcodeproj

Download the project

Animations and transformations

April 26th, 2009

Using right animation / transformation can improve quality of your application. There are most important during game development.

You can use 3 basic transformations – you can marge them or invent your own. These 3 animations are:

  • rotation
  • scale
  • translation

animationsimulator

You can apply animation to almost everything – images (UIImageView), buttons (UIButton), toolbars, label, views…

Rotation:

Let’s say you have an image (UIImageView *myImage) and you would like to do something with it. To rotate it:

myImage.transform = CGAffineTransformMakeRotation(M_PI*0.25);

This will rotate image by 45 degrees right. Here are the typical values and their degree equivalents:

  • M_PI * 0.00 = 0° (original condition)
  • M_PI * 0.25 = 45°
  • M_PI * 0.50 = 90°
  • M_PI * 0.75 = 135°
  • M_PI * 1.00 = 180°
  • M_PI * -0.75 = 225°
  • M_PI * -0.50 = 270°
  • M_PI * -0.25 = 315°

If you would like to use degrees not the range <-1 ; 1> multiplied by M_PI you can define the constant value in header of your class: #define radianConst M_PI/180.0 (right under the #import lines). Now if you want to turn your image by 63 degrees use this:

myImage.transform = CGAffineTransformMakeRotation(63.0*radianConst);

Scale

Scale allows you to zoom in / zoom out your image. It’s more than simple scale, you can set the scale parameter different for image’s width and height. If you would like to have the image 2 times wider and 1.5 times higher try this:

myImage.transform = CGAffineTransformMakeScale(2.0,1.5);

Don’t be surprised that after this operation your image will be pixeled, that’s why in future you should provide images in higher resolution make them smaller on load (for example CGAffineTransformMakeScale(0.5,0.5)) and later when needed show them in original dimensions using CGAffineTransformMakeScale(1.0,1.0).

Scale gives you one more cool effect. If you set scale parameter as a negative value your image will be scaled and flipped horizontally or vertically. Examples:

  • CGAffineTransformMakeScale(-1.0,2.0)image flipped horizontally and twice higher
  • CGAffineTransformMakeScale(1.5,-3.0) – image 1.5 times wider, 3 times higher and flipped vertically
  • CGAffineTransformMakeScale(-2.0,-2.0)image 2 times bigger and flipped both horizontally and vertically

Translation

Translation is doing almost the same thing as changing the center value of any object. It moves image along X and Y axises. It’s the poorest so I will give you only 1 example and won’t talk about this any more.

  • CGAffineTransformMakeTranslation(50.0,20.0)image moved 50 pixels to the right and 20 to the botton

Similar effect you will get using center as I mentioned before: myImage.center = CGPointMake(140.0,90.0). Both of them has their own advantages and disadvantages, but let’s now move to something more interesting.

Animations

You know how to rotate an image (or anything else) by given degree, scale, flip, or move. How about creating a smooth animation? Well it’s very simple:

	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:1.5];
	// other animations goes here
	myImage.transform = CGAffineTransformMakeRotation(M_PI*0.5);
	// other animations goes here
	[UIView commitAnimations];

This code will smoothly rotate your object by 45 degress during 1.5 seconds. Please note, that while performing any animation the application continue to run next tasks – doesn’t hold for a given amount of seconds. If you would like your app to do an action when the animation is finished you can use either the NSTimer:

[NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(nextMethodName) userInfo:nil repeats:NO];

or extend your animation code by it’s delegate and selector:

	[UIView beginAnimations:nil context:NULL];
	[UIView setAnimationDuration:1.5];
	[UIView setAnimationDelegate:self];
	[UIView setAnimationDidStopSelector:@selector(nextMethodName)];
	myImage.transform = CGAffineTransformMakeRotation(M_PI*0.5);
	// other animations goes here
	[UIView commitAnimations];

Remember that second example is much more efficient, but in that case, nextMethodName (whatever you name it) must return a boolean YES – not void which doesn’t return any value at all. Example:

-(BOOL)nextMethodName {
 	// some tasks
	return YES;
}

Animations can be great to have transitions between two views but I will talk about them in other article.

Two transformations at once

Using any of above transformations you are modyfing only one property – transform of a given object. For example the code:

myImage.transform = CGAffineTransformMakeScale(2.0,1.5);
myImage.transform = CGAffineTransformMakeRotation(M_PI*1.0);

will give you the image rotated by 180 degrees, but won’t be scaled – scale was canceled after making rotation.

If you would like to merge two transform use the following code:

animateLabel.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(2.0, 1.5), CGAffineTransformMakeRotation(M_PI*1.0));

I personally really don’t like this. I didn’t enjoy matrices during Mathematics in school. Any transform creates the matrix and CGAffineTransformConcat is multiplying two matrices – the order is necessary. If you wanted to merge three transforms you would have to use CGAffineTransformConcat merging two transforms as an argument of another CGAffineTransformConcat mergin previous merge with next transform. Sound difficult? Yes, for me two.

Original shape

To conclude, if you would like to quickly cancel any transforms use CGAffineTransformIdentity as a transform property of any object.

myImage.transform = CGAffineTransformIdentity;

I guess it’s all you need to know about transforms and animations right now. Below you can download my project where you can rotate, scale, translate any object using sliders and watch the smooth scale animation.

xcodeproj

Download the project

Saving data

April 26th, 2009

Saving data is an obvious part of most of your applications. In games you probably need to save records – names, scores, times, settings like the music volume. In applications you should save enabled options. If your application is big it’s great if you occasionally save the whole state / progress and even user terminates the app it can be restored during next launch.

Here you will learn how to save data locally on your device / simulator. It’s not as difficult it appears to be. Of course you could use an SQLite database and write a controller to inser / update / delete records but it’s much more advanced. From this tutorial you will learn how to use NSUserDefaults to save whatever you need.

The syntax is simple. To save your data use this code:

	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	[defaults setInteger:5 forKey:@"myNumber"];
	[defaults setBool:YES forKey:@"switchEnabled"];
	[defaults setFloat:0.24 forKey:@"sliderValue"];
	[defaults setObject:@"Chris" forKey:@"myName"];
	[defaults synchronize];

As you see above I have saved 4 values. myNumber is an integer and =5. switchEnabled is a boolean with logic value YES / true. sliderValue is a float and =0.24 and myName is an object – it’s a NSString and it holds English equivalent of my name :) .

Now, to get values from any key you can use only one line of code for example:

	int anInteger = [[NSUserDefaults standardUserDefaults] integerForKey:@"myInteger"];
Since now anInteger=5.
If you try to load a value that doesn’t exist you will get 0 for integers, doubles, floats, NO for booleans and nil for objects.

I prepared for you a project, where 3 different values are saved during any change, and loaded with the launch of the application. You can change there slider value, enter your name, and press the button – whenever the button is pressed the value below grows. You can quit and launch the application and see what happens.

savesimulator

xcodeproj

Download the project

Alerts

April 26th, 2009

uialertviewAlerts are widely used in many ways. Very often they are shown on first run to say hello. Also to inform you about something necessary, important. They ask you to wait several seconds, display warnings, errors.

In fact they look just great, stunning and they suits almost any game / application interface. End user might think that we did a lot of hard work to display something so polished like this while it actually only few lines of code.

To display an alert (UIAlertView) like on the screenshot above you need to add:

	UIAlertView *simpleAlert = [[UIAlertView alloc] initWithTitle:@"Alert's title" message:@"This is an alert's message." delegate:self cancelButtonTitle:@"and the" otherButtonTitles:@"buttons",nil];
	[simpleAlert show];
	[simpleAlert release];

You can show the alert wherever you like in you application for example in viewDidLoad method or after pressing button. If you alert has more than two buttons they will be displayed in a single column, not row:

alertview3buttons

As long as you won’t add an UIAlertViewDelegate protocol to your class and implement  alertView:clickedButtonAtIndex: method, pressing any button will only dismiss your alert. Protocol is added in header file of your class:

@interface MyView : UIViewController <UIAlertViewDelegate> {

If you have more than one protocol separate them with commas: <oneProtocol, theOtherProtocol>. Now in implementation (.m) file add this method:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
	if (buttonIndex == 1) {
		// do something
	}
	else if (buttonIndex == 2) {
		// do something
	}
}
As usuall first button (in 99% cancel button) has index = 0. If you have more than one “complex alert” and each of them has different roles it’s good to use tags for them and check in alertView:clickedButtonAtIndex: what value an alert’s tag has which called this method.
	UIAlertView *complexAlert = [[UIAlertView alloc] initWithTitle:@"Complex Alert" message:@"Select an action" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Sure",@"Not sure",nil];
	complexAlert.tag = 1;
	[complexAlert show];
	[complexAlert release];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
	if ([alertView tag] == 1) {
		if (buttonIndex == 1) {
			// do something
		}
		else if (buttonIndex == 2) {
			// do something
		}
	}
	else {
		// do something
	}
}
That’s almost all you need to know about alerts but there is one more interesting thing. If you would like to dismiss an alert after several seconds – for example a welcome screen or activate a default option, follow this example:
	autoAlertView = [[UIAlertView alloc] initWithTitle:@"Auto-dismissed Alert" message:@"This alert will be dismissed in 5 seconds." delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
	userDismissed = NO;
	[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(dismissAlert) userInfo:nil repeats:NO];
	[autoAlertView show];
-(void)dismissAlert { if (userDismissed) return; [autoAlertView dismissWithClickedButtonIndex:0 animated:YES]; [autoAlertView release]; }
As usuall you can download a sample project here:
xcodeproj

Touches

April 26th, 2009

Touches are handled by three methods:

  • touchesBegan:
  • touchesMoved:
  • touchesEnded:

To have access to touches you need to code these 3 methods (or one/two of them).

The code is very simple:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
} 
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
}

touchesBegan: will be called whenever user touch the screen with one finger, and each time new touch is declared for example with the second finger, nose ear, battery, foot…

touchesEnded: will be called whenever any single touch is ended

touchesMoved: hmmm it’s not so clear as you might think. Yes, this method will be called if any finger moves while touching the screen, but on real device this method is called almost immidietely after touchesBegan. Why is that? On iPhone simulator mouse plays role of the finger, so you can press and release the mouse/touch-pad button and both touchesBegan and touchesEnded will be called, but not touchesMoved provided that you won’t move a pointer. If you touch an iPhone / iPod screen in 99% the coordinates of where the touch started and ended will be different, so meanwhile touchesMoved will be called.

You probably woud like to know what are the touch coordinates, it’s very easy to get them. Extend any of above three methods with this code:

	UITouch *touch = [touches anyObject];
	CGPoint touchCoordinates = [touch locationInView:self.view];

touchCoordinates.x and touchCoordinates.y give you information you need.

If you would like to have details of more than single touch (you can touch the screen with as many fingers you want), this might be helpful:

	NSSet *allTouches = [event allTouches];
	UITouch *singleTouch;
	for (int i = 0; i < [allTouches count]; i++) {
		singleTouch = [[allTouches allObjects] objectAtIndex:i];
		// whatever you need goes here
	}

If you would like to simply know how many fingers are touching the screen use [allTouches count]; with first line of above example.

If you want to do something when users double tap the screen for example try:

	if ([touch tapCount] == 2) {
		// whatever you need goes here
	}

You can use only tapCount for the single touch. Taps aren’t counted for multiple touches.

Now something more interesting. How to check if user touched an object like image, label…? Before you enter any code in the attributes in Interface Builder of your item enable option: User Interaction Enabled and Multiple Touches if needed. views have User Iteraction enabled by default. You can also do it in XCode:

	myObject.userInteractionEnabled = YES;
	myObject.multipleTouchEnabled = YES;

Once User Interaction is enabled you can use if statement to perform any task:

	if ([touch view] == myObject) {
		// whatever you need goes here
	}

touchessimulator I guess it’s all you need to know about touches. I prepared for you a project you can download. It gives you all information:

  • where the touch began (x,y)
  • where the touch moved (x,y)
  • where the touch ended (x,y)
  • how many fingers touched the screen (in touch began)
  • the tap count
  • and a Move Me square you moves by moving your finger

xcodeproj

Download the project

Interface Builder

April 26th, 2009

interfacebuilder

dev_interfacemedium

Interface Builder is a great utility for new developers. As you might know, it’s used to design your user interface.

In fact, everything you create in Interface Builder you can also programmatically in Xcode. What is more Xcode given you more possibilities of customization any objects like sliders, toolbars, switches, images, text fields and more.

So what are advantages and disadvantages of using Interface Builder?

Disadvantages? None. Advantages? A lot of!

Interface Builder is a great utility that allows you to visually create an interface, not to guess what is the proper width, height and placement using X and Y coordinates. You can create almost every 2D game and application faster if using Interface Builder. It makes your code shorter – you don’t have to create the outlets manually, they are already created for you.

I will show you an example. How to create programmatically in Xcode a label:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 50.0, 70.0, 30.0);];
label.textColor = [UIColor blueColor];
label.backgroundColor = [UIColor brownColor];
[label setText:@"My Text"];
label.textAlignment = UITextAlignmentCenter;
[self.view addSubview:label];

You will obtain the same result dragging & dropping the label from the I.B. Library to the view. Customization – like changing the text or background colour can be chosen from it’s menus, and while doing this, you track the changes and have full control if the new look matches the interface. But, customization is limited to keep I.B. window clear. You can’t rotate an label for example, but once you created an object and connected it to the right outlet Xcode can do the rest.

That was only an example. Interface Builder is really helpful and being a good programmer doesn’t mean the you have to use only Xcode. Relax, and play with I.B. every static content can be loaded from .xib files I.B. creates for you. Xcode will be necessary usually only if there is unknown number of objects to be displayed in the application.

Simple Calculator

April 25th, 2009

You can already build a Hello World application (I hope so). Now, let’s try to build something more interesting with more user functionality.

Start Xcode, create new project Window-Based Application, name it Calculator, create a View Controller, name it Calc, create a view name it Calculator.

You have to create one object, few variables and methods in Calc.h file:

#import <UIKit/UIKit.h>
@interface Calc : UIViewController {
	float result;
	IBOutlet UILabel *calculatorScreen;
	int currentOperation;
	float currentNumber;
}
-(IBAction)buttonDigitPressed:(id)sender;
-(IBAction)buttonOperationPressed:(id)sender;
-(IBAction)cancelInput;
-(IBAction)cancelOperation;
@end
  • result of type float is a number in memory – result of the last operation
  • calculatorScreen of type UILabel shows the result of the operation or a number user is entering
  • currentOperation of type int is and ID of operation (1 – addition, 2 – subtraction, 3 – multiplication, 4 – division, 0 – equals)
  • currentNumber of type float is the number user is entering for every next operation (displayed on calculatorScreen)
  • buttonDigitPressed:(id)sender method is called whenever user press one of 0-9 buttons, as you see I use only one method for all of ten buttons. Of course I could implement ten methods like: -(IBAction)button6Pressed, but I will show you how to detect, which button called the method using (id)sender
  • buttonOperationPressed:(id)sender the same as above, one method for 5 operations: addition, subtraction, multiplicationdivision and equals
  • cancelInput and cancelOperation when user presses “C” or “AC”

Now open Calculator.xib and drag’n'drop 17 buttons and one label and do with them the same what I did below:

calculatorview

Remember to resize the Label so the bigger numbers fit there without difficulties. Open the Inspector, click on each 0-9 buttons and in Button Attributes set 0, 1, 2, 3, 4… as a Tag [Tag = 5 for 5 Button, Tag = 7 for 7 Button]… Do the same with operation buttons: Tag = 1 for addition, 2 for subtraction, 3 for multiplication, 4 for division, 0 for equals but as zero is a default tag you don’t have to enter it manually.

tagbutton1

tagbuttonx

Now, select File’s Owner from Calculator.xib and Object Identity enter Calc as Class. Now in Calc Connections connect in the same way you did in Hello Worldview to the view, calculatorScreen to the label. And now connect actions to the buttons. Connect buttonDigitPressed: to the 0 Button’s Touch up inside. Although now this method is called by 0 Button, you can connect more buttons to it. Press again on the circle next to buttonDigitPressed: and connect it to 1 Button this time. If it worked, connect it to the next 2-9 Buttons. Do the same with buttonOperationPressed: and connect it with equals, addition, subtraction, multiplication, division, later connect cancelInput with “C”, and cancelOperation with “AC”.

calcconnections

That’s all you have to do in Interface Builder. Save Calculator.xib and go back to Xcode.

You have to put these standard lines of code in CalculatorAppDelegate.h/.m files:

#import "Calc.h"

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

just like in Hello World example (did you read it?).

If you press Build and Go you should see your project in iPhone Simulator, but it won’t do any calculations because you provided so far only methods names in the header of class Calc (in Calc.h file). Now you have to implement them in Calc.m.

-(IBAction)buttonDigitPressed:(id)sender

-(IBAction)buttonDigitPressed:(id)sender {
	currentNumber = currentNumber*10 + (float)[sender tag];
	calculatorScreen.text = [NSString stringWithFormat:@"%.2f",currentNumber];
}

Each time above method is called the currentNumber value is changed. [sender tag] is giving you the number you entered as a tag of each of 0-9 buttons. Below is the example how currentNumber looks like after pressing digits:

  1. 0 (original value)
  2. user presses “5″: 0*10 + 5 = 5
  3. user presses “9″: 5*10 + 9 = 59
  4. user presses 2: 59*10 + 2 = 592

calculatorScreen text is also changed showing the user the number he is entering right now. If you can’t figure out what this line exactly do, go here: http://www.cplusplus.com/reference/clibrary/cstdio/printf/ .

-(IBaction)buttonOperationPressed:(id)sender

-(IBAction)buttonOperationPressed:(id)sender {
	if (currentOperation == 0) result = currentNumber;
	else {
		switch (currentOperation) {
			case 1:
				result = result + currentNumber;
				break;
			case 2:
				result = result - currentNumber;
				break;
			case 3:
				result = result * currentNumber;
				break;
			case 4:
				result = result / currentNumber;
				break;
			case 5:
				break;
		}
	}
	currentNumber = 0;
	calculatorScreen.text = [NSString stringWithFormat:@"%.2f",result];
	currentOperation = [sender tag];
}

When the application runs each int value is set to zero so when the user press any operation button the current number displayed on “screen” is treated as the result and the ID of operation is saved to currentOperation. Every next time currentOperation remembers the pressed operation button and perform expected operation. Below is example how above method works:

  1. user enters 123 and presses the addition
  2. user enters 354 and presses the subtraction
  3. 123+354 = 477
  4. users enters 10 and press equals
  5. 477 – 10 = 467

-(IBAction)cancelInput & -(IBAction)cancelOperation

-(IBAction)cancelInput {
	currentNumber = 0;
	calculatorScreen.text = @"0.00";
}

-(IBAction)cancelOperation {
	currentNumber = 0;
	calculatorScreen.text = @"0.00";
	currentOperation = 0;
}

Above two methods look almost the same. Both of them set zero as currentNumber, changes the screen text so it shows 0.00. The only difference is that cancelOperation set also zero as currentOperation – just like user would reopen the application or hit the equals.

You can Build and Go to see your application running, your calculator should work now. It’s only a simple example, division by zero is accepted, you can’t enter fractions, but I hope you learn something from me today.

calculatorsimulator

And again one small thing. Memory management. In fact it’s a big thing. In dealloc method add [calculatorScreen release];. You have to release only objects you, or Interface Builder allocated for you, so the calculatorScreen needs to be released. You don’t have to worry about variables – ints, floats, booleans

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.

iPhone Simulator

April 24th, 2009

simulator1simulator2simulator3

dev_simulatormediumiPhone Simulator is a tool that allows you to quick debug your applications. It’s almost the perfect copy of the real device, but it has some major and minor differences. The main advantage of using the simulator is that applications get loaded within few seconds. You can/should use simulator on the early stage of development.

Differences:

  • although there is almost the same environment, iPhone simulator doesn’t run as much system application as the real devices, so the bigger applications can run smoothly on simulator bot do not on real device
  • internet access to simulator is only passed via computer and treated like WiFi a, you cannot test how your application is using 3G or other cellular data transfer
  • you can’t control acceleration, you can turn the iPhone landscape and portrait mode, but you cannot tilt it to controls the games using accelerometer
  • you can’t use GPS feature to get location or track its changes
  • you can “touch” the simulator using one “finger” or two (hold the option key), but it’s impossible to use most of multi touch gestures or touch simulator with more “fingers”
  • you can’t use vibration alert
  • many sounds or musics won’t play on simulator, what is more some frameworks and classes to hold the sounds cannot be compiled to run on simulator
  • you can’t use a camera
  • you don’t risk damaging the real device if you get frustrated
  • iPhone simulator cannot be jailbroken, or I don’t know how
  • you can’t put any case on it

iPhone Simulator has almost the same functionality as a real device. You terminate an application by pressing the home button, you can turn it left, right, toggle in-call status bar, simulate memory warning and lock it. When installed you have access to apps like: Photos (with some albums), Settings (General, Safari and Photos settings), Safari and Contacts. To install your own app on simulator, in Xcode set Simulator – iPhone OS [firmware version] as Active SDK an Debug as Active Build Configuration.