How To Make An Orientation-Aware Clock

iphone_clock

For this tutorial we’re going to build a simple clock that is orientation-aware, meaning that when you rotate your iPhone, the time rotates with it. I’m assuming you have a basic knowledge of the iPhone SDK.

To get started, you will need a label for the time and a background image. You will also need a timer. To get started, you must declare your outlets in code before Interface Builder will be able to use them. I’ll show you how to do that now.

Let’s Get Our Hands in Some Code

Edit SimpleClockViewController.h so it looks like this:

1#import
2
3@interface SimpleClockViewController : UIViewController {
4 IBOutlet UILabel* clockLabel;
5 NSTimer *myTicker;
6}
7
8@end

The myTicker is going to be responsible for updating the clockLabel. We will implement that code later.

The next thing you want to do is drag background_image.png to your project (see image below). You can get the image here.

image-510

You want to copy the item to the project’s directory so put a check mark next to “Copy items into destination group’s folder (if needed).” Your settings should look similar to this. Click Add.

2009-03-09_1229

Open SimpleClockViewController.xib. Drag UIImageView from the Library to the View window. This will act as a placement holder for our background image.

image-5101

Bring up the Attributes Inspector. Set the Image to background_image.png. Set the Mode to Scale To Fill so that the background_image.png stretches out when we rotate the iPhone.

2009-03-06_15431

Bring up the Size Inspector and change the Autosizing settings to look like this. The arrows in the Autosizing box act as outward springs, which cause the view to resize itself proportionally based on the width or height of its superview. The “I”s act as struts that keep a fixed distance when the View is changed when you rotate the iPhone. If that’s hard to visualize, Interface Builder has an animation to the right of the Autosizing box will help you visualize its current settings.

2009-03-06_1545

Drag a Label to the View window and resize to approximately the width of the window. Center it. This makes the time larger and also positions the time to be rotated around its center point when you turn the iPhone into landscape mode.

image-5102

Change the font of the label by selecting the Label and hitting Command-T. Change the settings so you’re using Helvetica, Bold, size 48.

2009-03-06_15561

Bring up the Attributes Inspector. Change the Layout Alignment to Center. Again, we’re doing this so the time rotates around its center. Change the font color to white so it looks good on the dark background. It should look similar to this:

2009-03-06_1557

Bring up the Size Inspector and change your Autosizing settings to look like the image below. This makes sure the time rotates and positions itself correctly around its center.

2009-03-06_1557a

Lastly, Control-Drag from File’s Owner to the Label and choose clockLabel when the outlet box pops up. This tells your Label which variable it is in the code.

2009-03-09_1311

Save and close Interface Builder. Back in Xcode, open SimpleClockViewController.h and add runTimer and showActivity methods. These declare the functions we’re going to write.

01#import
02
03@interface SimpleClockViewController : UIViewController {
04 IBOutlet UILabel* clockLabel;
05 NSTimer *myTicker;
06}
07
08/* New Methods */
09- (void) runTimer;
10- (void)showActivity;

Open SimpleClockViewController.m and add the methods we just declared.

01- (void)runTimer {
02 // This starts the timer which fires the showActivity
03 // method every 0.5 seconds
04 myTicker = [NSTimer scheduledTimerWithTimeInterval: 0.5
05 target: self
06 selector: @selector(showActivity)
07 userInfo: nil
08 repeats: YES];
09
10}
11
12// This method is run every 0.5 seconds by the timer created
13// in the function runTimer
14- (void)showActivity {
15
16 NSDateFormatter *formatter =
17 [[[NSDateFormatter alloc] init] autorelease];
18 NSDate *date = [NSDate date];
19
20 // This will produce a time that looks like "12:15:00 PM".
21 [formatter setTimeStyle:NSDateFormatterMediumStyle];
22
23 // This sets the label with the updated time.
24 [clockLabel setText:[formatter stringFromDate:date]];
25
26}

The runTimer method only has 1 line of code split into multiple lines. All it does is call the showActivity method every 0.5 seconds.

The showActivity method formats the clockLabel so it looks like “12:15:00 PM” and sets it to the current time. As mentioned above, this method is called every 0.5 seconds.

We want to call runTimer after the view loads. This is a common method that, when Xcode generated SimpleClockViewController.m, they included a method called viewDidLoad. This method is called immediately after the View items are loaded. Find the viewDidLoad method and uncomment it.

Add [self runTimer]; to the end of the method. It should now look like this:

1// Implement viewDidLoad to do additional
2// setup after loading the view, typically from a nib.
3- (void)viewDidLoad {
4 [super viewDidLoad];
5
6// This calls the runTimer method after loading
7// SimpleClockViewController.xib
8 [self runTimer];
9}

When Xcode generated SimpleClockViewController.m, they also included shouldAutorotateToInterfaceOrientation. By default, views display only in portrait orientation, so you need to implement shouldAutorotateToInterfaceOrientation method if you want to support other orientations.

Locate the shouldAutorotateToInterfaceOrientation method and uncomment it. You can support only some orientations such as portrait or landscape with Home button on the right, but we don’t need to limit ourselves to those scenarios. We want to support all orientations so the view rotates correctly no matter how we’re holding the iPhone. To do this, replace return (interfaceOrientation == UIInterfaceOrientationPortrait); with return YES;.

1// Override to allow orientations other than
2// the default portrait orientation.
3- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
4 // Return YES for supported orientations
5 return YES;
6}

Now you can build and run it! Hit Command-Left to see your UI rotate with the iPhone simulator. You can Build and Run the project to make sure everything is compiling and running.