Today, a quick guide through basic location services on the iPhone 3G (i.e. I’m not handling heading information here.) I run through a quick overview of the steps involved in building a basic location-aware app, and provide a complete Xcode project for your perusal.
The Goal
I want to build a simple GPS console, that will provide:
- Latitude/Longitude (w/ accuracy)
- Altitude (w/ accuracy)
- Course and Speed
Fortunately, this is really easy.
Getting Started
Open Xcode, and start a New Project. Choose to create a “View-Based Application” when asked. You’ll be able to use the application delegate and main window NIB files exactly as they were created for you.
Frameworks
The biggest gotcha is failing to add the Core Location framework to your project. Right-click your target, then select “Add”->”Existing Frameworks…”. Click the plus icon underneath the Linked Libraries pane, and add the CoreLocation framework.
Members and Outlets
Open the Xcode-created View Controller .h file, and alter its definition to look like this:
@interface LocXViewController : UIViewController <CLLocationManagerDelegate>
{
CLLocationManager* manager;
NSDateFormatter* formatter;
UILabel* latitude;
UILabel* longitude;
UILabel* h_accuracy;
UILabel* altitude;
UILabel* v_accuracy;
UILabel* course;
UILabel* speed;
UILabel* updated;
UILabel* updated_suffix;
}
@property (nonatomic, retain) IBOutlet UILabel* latitude;
@property (nonatomic, retain) IBOutlet UILabel* longitude;
@property (nonatomic, retain) IBOutlet UILabel* h_accuracy;
@property (nonatomic, retain) IBOutlet UILabel* altitude;
@property (nonatomic, retain) IBOutlet UILabel* v_accuracy;
@property (nonatomic, retain) IBOutlet UILabel* course;
@property (nonatomic, retain) IBOutlet UILabel* speed;
@property (nonatomic, retain) IBOutlet UILabel* updated;
@property (nonatomic, retain) IBOutlet UILabel* updated_suffix;
@end
(Remember to #import
CoreLocation/CoreLocation.h
in this header file.)
Next, open the View Controller .m file, add @synthesize
statements, and recode dealloc
thusly:
@implementation LocXViewController
@synthesize latitude;
@synthesize longitude;
@synthesize h_accuracy;
@synthesize altitude;
@synthesize v_accuracy;
@synthesize course;
@synthesize speed;
@synthesize updated;
@synthesize updated_suffix;
// ... etc ...
- (void)dealloc
{
[manager release];
[formatter release];
[latitude release];
[longitude release];
[h_accuracy release];
[altitude release];
[v_accuracy release];
[course release];
[speed release];
[updated release];
[updated_suffix release];
[super dealloc];
}
// ... etc ...
@end
Finally, save your work and open up the View Controller NIB in Interface Builder. Design an output screen that appeals to you. Connect up the outlets you just created to the labels that will display the various data elements. (In the project packaged with this post, I provide a sample NIB file.)
Payoff
Only two bits of code need to be added to make this application “go”. First, override the designated initializer:
- (id)initWithCoder:(NSCoder*)coder
{
if (self = [super initWithCoder:coder])
{
formatter = [[NSDateFormatter alloc] init];
formatter.AMSymbol = @"am";
formatter.PMSymbol = @"pm";
formatter.dateFormat = @"h:mm:ssa";
manager = [[CLLocationManager alloc] init];
manager.delegate = self;
[manager startUpdatingLocation];
}
return self;
}
Last, implement one CLLocationManagerDelegate
method:
- (void)locationManager:(CLLocationManager*)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation*)oldLocation
{
if (newLocation.horizontalAccuracy < 0)
{
latitude.text = @"N/A ";
longitude.text = @"N/A ";
h_accuracy.text = @"N/A ";
}
else
{
latitude.text = [NSString stringWithFormat:@"%.6f",newLocation.coordinate.latitude];
longitude.text = [NSString stringWithFormat:@"%.6f",newLocation.coordinate.longitude];
h_accuracy.text = [NSString stringWithFormat:@"%d",(int) newLocation.horizontalAccuracy];
}
if (newLocation.verticalAccuracy < 0)
{
altitude.text = @"N/A ";
v_accuracy.text = @"N/A ";
}
else
{
altitude.text = [NSString stringWithFormat:@"%d",(int) newLocation.altitude];
v_accuracy.text = [NSString stringWithFormat:@"%d",(int) newLocation.verticalAccuracy];
}
course.text = (newLocation.course<0)?@"N/A ":[NSString stringWithFormat:@"%d",(int) newLocation.course];
speed.text = (newLocation.speed<0)?@"N/A ":[NSString stringWithFormat:@"%d",(int) newLocation.speed];
NSString* ts = [formatter stringFromDate:newLocation.timestamp];
updated.text = [ts substringToIndex:[ts length]-2];
updated_suffix.text = [ts substringFromIndex:[ts length]-2];
}
Sample Code
You can download an Xcode project implementing the sort of application we’ve just built here. (Note that this project is slightly more elaborate, and adds an on/off switch for location updates.)
Hi, Michael.Thank you so much for sharing this. For you, maybe it’s just an easy task. For me, a novice level ios programmer, it’s a wonderful article to read.Thank you again.
Tommy