iPhone speed gauge, compas or clock component

May 20th, 2011 No Comments »

Hi there, this is a tutorial, with full source code and a functional example of how to create a round gauge or clock component for iPhone.

This tutorial is very useful because it also shows you the principles and the best practices to create a custom component.

This tutorial will show you how to create an animated gauge just like this :

The final gauge

The final gauge

The component we create can be skied with any images you want, it can be a speed gauge, a compass or anything you want, it will be auto scalable and one line integration.

The principle it’s simple, we just extend the view and in it we add our code to create the gauge, in this case the gauge is very simple, it only has a background image and a pin which you can rotate to a specific angle in degrees.

So, here goes :

1. Download the files located here, this is the View subclass i created and the images needed for the project, both high and low resolution.

2. Create a view based project, this is the easiest solution for exemplification. My project is called “Gauge” so all the names of the view controllers will be relative to this, it would be easier for you if you name your project the same.

Create a new view based project

Create a new view based project

3. Add the files to the project (check the copy to project option)

Add the files to the project

Add the files to the project

and this how the project structure will look like when you are done (i created a separate images directory, so the tree looks cleaner) :

Xcode project structure

Xcode project structure

4. We should create an outlet for a ClockView, which we will add in the project. In this example I will only use one gauge, but you can follow the process to create as may as you want.
Now open the “GaugeViewController.h” file and change it so it looks like this :

#import

@class ClockView;

@interface GaugeViewController : UIViewController {

  ClockView *gauge1_;
}

@property(nonatomic, retain) IBOutlet ClockView *gauge1;

@end

What we did here is to add a forward declaration for the ClockView and declare an outlet to a ClockView view, remember that ClockView is a subclass of UIView, so it can be used in any way a view can be used. Now open the “GaugeViewController.m” and add the code bellow right after the “@implementation GaugeViewController” line :

@synthesize gauge1 = gauge1_;

and also this is how dealloc method should look now :

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

5.Now open the “GaugeViewController.xib” file, here we add our clock view. We add it as a normal UIView, so you should add a view from the library to your main view (as a child of the main view), the view you add should be square :

Add a new subview

Add a new subview

6. We have to set the new view to be a clock view, we do this by changing the class of the view we added from UIView to ClockView :

Change the class of the UIView

Change the class of the UIView

And also set the outlet of the view to the outlet we created earlier :

set the outlet

set the outlet

And we are done with the xib file, save it!

7. Open once again the “GaugeViewController.m” file. Include the ClockView.h file. Update the viewDidLoad method, which should look like the one bellow :

- (void)viewDidLoad
{
    [super viewDidLoad];
  [gauge1_ prepare];
}

8. We are almost done, one more small thing remaining. The ClockView uses some layer methods to transform it, and those methods are found in Quartz2d frame work, so we have to add it. So add the Quartz2D framework :

add quartz2d framework into the project

add quartz2d framework into the project

9. Build and run the project :D :

Run the clock view project

Run the clock view project

The pin of the gauge is very easy to rotate, by calling the rotateTo method of the clock view.

As an extra bonus step, let’s make the clock to make an full rotation every minute, and update it every second. We will do this by adding a timer to the project, and an integer to count the seconds.

Open the “GaugeViewController.h” and change it to :

#import

@class ClockView;

@interface GaugeViewController : UIViewController {

  ClockView *gauge1_;
  NSInteger seconds_;
}

@property(nonatomic, retain) IBOutlet ClockView *gauge1;

@end

All I did was to add a new NSInteger variable.

Now open the GaugeViewController.m and add a timer and a method which is called every second :

- (void)viewDidLoad
{
    [super viewDidLoad];
  [gauge1_ prepare];
  [NSTimer scheduledTimerWithTimeInterval:1.0f
                                   target:self
                                 selector:@selector(secondUpdate:)
                                 userInfo:nil
                                  repeats:YES];
}

-(void)secondUpdate:(NSTimer*)timer {
  //we have 360 degrees on a full rotation, and we want 60 steps per rotation
  [gauge1_ rotateTo:seconds_*(360/60)];
  seconds_++;
}

Run the project once again and observe the results.

Here is the entire project if you want it.

Adding a UITextField inside an UIAlertView

August 17th, 2010 1 Comment »

Hi, i’m sure that you wondered how you can create an input inside an alert, those password alerts, or just to enter a single value like name or something like this.

The solution is very simple and efficient, everything you should know is that both the alert and the text field are actually views, so you can add an view inside an other view using the addSubview:view method… yes, it’s that simple, anyhow here is how you can do it.

I will guide you step by step to do this in a simple project, but you can integrate this as it is in any other projects, just follow the steps.

First, create a new view based project and add a method which will be called when you press a button, you .h file of the view controller should look something like this :


#import <UIKit/UIKit.h>

@interface alertViewController : UIViewController {

}

-(IBAction)buttonPressed:(id)sender;

@end

Now also add the method in the .m file, for now it’s just going to be empty, we will add the code later. Add this just before the @end liness :


-(IBAction)buttonPressed:(id)sender {

}

Now, go to interface builder, drag a button from the library and connect the event to the method :

link the action to the method

link the action to the method

You are now done with interface builder, you can close it and return to xCode.

Go to the method you just entered and enter the code :


UIAlertView *alert = [[[UIAlertView alloc]initWithTitle:@"Add Tag"
 message:@" "
 delegate:self
 cancelButtonTitle:@"Add"
 otherButtonTitles:@"Cancel",nil]autorelease];
 UITextField *tagField = [[[UITextField alloc]
 initWithFrame:CGRectMake(20.0, 45.0, 245.0, 25.0)]
 autorelease];
 // tagField.
 tagField.backgroundColor = [UIColor whiteColor];
 tagField.tag = 10;

 [alert show];
 [alert addSubview:tagField];

The code is pretty straight forward, we create an alert view and a text field, set the frame for the text field add a white background to the text field so it can be seen, and also add a tag for the button so we can retrieve it at a later time, then the alert is shown and the text field is added.

Regarding the background of the uitextfield, by default it looks like it’s transparent…. so if you don’t add the color you will think that the field is not added, actually it’s there, you can click it but you can’t see it… it happened to me, so don’t do this mistake again.

In this example I used an alert view to add a tag, but you can use it for what ever you want, if you want a simple way to add a value.

Now, go back to the .h file and add the UIAlertViewDelegate


@interface alertViewController : UIViewController <UIAlertViewDelegate> {

We have to do this so we can track when the user clicks one of the buttons from the alert. You can also build and run now, but no matter what button you press the action will be the same.

To get the actions add this code :


- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
 //the add button
 UITextField *tagName = (UITextField*)[alertView viewWithTag:10];
 if(buttonIndex == 0) {
 if(tagName.text != nil) {
 // do some tag adding
 }
 }
 [tagName removeFromSuperview];
}

You can see that we are using the tag we set earlier to get the text view.

Also this method is called before the alert is dismissed so theĀ  text view is removed avoiding warnings that appear when the alert view is dismissed.

And this is it, you can build and run and see the results :

alert view with text field

alert view with text field

alert view with text field

alert view with text field

Please do not hesitate to ask me any questions if you have any!

Create a custom UIViewCell on iPhone

August 12th, 2010 No Comments »

In this short tutorial I will explain how to create and use an UITableView that has custom cell, that are loaded from a diferent xib file.

In this tutorial you will also learn how to create a simple table view, connect an outlet to it, and also create it’s datasource and delegate.

This is helpful when you have tables that have complicated designs for the cells and you don’t want to create them from code, and it’s much easier to change.

So create a new viewbased project, right click on classes and add file, select a cocoa touch class and select the options like in the image bellow :

create new uitableview cell

create new uitableview cell

click next and name it something like “ACellView”, remember to check the also create h file button if it’s not checked.

Now we have t0 create the xib file for the cell : right click resources folder , add, and add file and select user interface and an empty xib file :

create new empty xib for cell

create new empty xib for cell

Now double click the xib file to actually create the cell view :

First of all, we have to create a view for the cell, this is not just a view it’s a table cell view, if you look in the library you will see this kind of view, drag one :

drag a cell view

drag a cell view

After you added the view, you have to identify the view, go to the identity inspector and select the class of the cell, this is the class previously created.

change identity of the cell view

change identity of the cell view

You also have to set an unique cell identifier, this is used for memory management to reuse cell, and not allocate new ones, it’s a huge memory improvement, especially when you are working with tables which have a large number of cells.

add unique cell identifier

add unique cell identifier

And the final step is to add a label to the cell view, we can add here whatever we want, but just for the demo we will add a simple label.

add a lablel

add a lablel

Now, open your viewcontroller header file, it should only be one header file which containts “viewcontroller” and copy the code(remember to change the name of the view controller so it matches yours :

#import <UIKit/UIKit.h>

@interface TVC2ViewController : UIViewController
<UITableViewDelegate, UITableViewDataSource>{

 UITableView *tableView_;

}

@property (nonatomic, retain) IBOutlet UITableView *tableView;

@end

You can see that we added one the datasource and the delegate for a table view, also we added an outlet to a table view, now it’s time to connect them to the table view, but before we do that enter the following line after the implementation line in your m file of the view controller :

@synthesize tableView = tableView_;

Now in the resources group double click the main view xib file, it has the same name as the view controller, the interface builder will open with the empty view.

Now we will create a table view and link it to out outlet, also we will set the datasource and delegate for the tableview.

adding a table view

adding a table view

Just drag a table view from the library to the view, this is very simple, also the table view will take the size of the view, but you can than resize it to any size you want.

Next we connect out outlet to the table view :

connecting the outlet

connecting the outlet

Now we have to set the datasource and delegate for the table view, without them the table view will display no data. The data source will be used to retrieve the table data, like the number of sections, number of rows, etc. The delegate will be called when certain actions are triggered, like selecting a cell, or just before selecting a cell.

If the connection inspector is not opened you can open it from tools menu.

adding the datasource

adding the datasource

And now you should be done with the xib, select the table view and take a look in the connection inspector, it should look like in the image bellow :

check the connections

check the connections

Now that this is done all we have left to do is create some code to have some data, and implement the delegate and data source.

Go to the .m file of you view controller, and scroll down at the end of the file and paste in the code :


#pragma mark -
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
 return 5;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

 NSString *CustomCellIdentifier = [NSString stringWithFormat:@"CustomCell"];

 ACellView *cell = (ACellView *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];
 if (cell == nil)
 {
 NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ACellView" owner:self options:nil];
 cell = (ACellView *)[nib objectAtIndex:0];
 }

 return cell;

}

#pragma mark -
#pragma mark Uitableviewdelegate
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 return NO;
}

If you compile now you will get an error, because you did now included the cellview file, just import the ACellView.h file, compile it, and everything should be ok.

program is running

program is running

As a final note, please keep in mind that the code above is just the base to start it working, the number of cells is hardcoded, and we are not setting any content to the cells, to do that you will have to add some outlets… maybe I’ll write about that in a future tutorial.

If you have any problems, or questions please do not hesitate to ask, and I will answer ASAP.

iPhone Development – Generating random numbers

June 22nd, 2010 No Comments »

this is a very short trick for generating random numbers when developing for iphone. There are many ways but this worked very fine for me and has some advantages over other methods here are some examples :


NSInteger randomNumber0_100 = arc4random()%100;

NSInteger randomNumber50_100 = arc4random()%50 + 50;

CGFloat randomFloat0_1 = (float)(arc4random()%100/100.0f);

There are 3 examples which show how to generate different ranges of random values.

The arc4random() function uses the key stream generator employed by the
arc4 cipher, which uses 8*8 8 bit S-Boxes. The S-Boxes can be in about
(2**1700) states. The arc4random() function returns pseudo-random num-bers numbers
bers in the range of 0 to (2**32)-1, and therefore has twice the range of
rand(3) and random(3).

How to create a vertical UISlider

June 21st, 2010 No Comments »

I’m sure that all of you wondered how to do this, and actually it’s pretty easy.

In my case i needed a zoom slider, and i want it vertical, as you can see there is no rotation option in interface builder, so how can you do that ? you can create an vertical slider from code: just add the slider from interface builder, and create an outlet, connect it to the slider and enter this in the viewDidLoad method of the view controller, you should have something like this :


- (void)viewDidLoad {
zoomSlider_.transform = CGAffineTransformRotate(zoomSlider_.transform, M_PI/2);
[super viewDidLoad];
}

The CGAffineTransformRotate function accepts 2 parameters, the first one is the current transformation and the second one is the number of radians to rotate (a radian = pi = 180 degree, so 90 = pi/2).