Adding Local Weather Conditions To Your App (Part 1/2: Implementing CoreLocation)

September 3rd, 2010 Posted by: Matt Tuzzolo - posted under:Tutorials

Knowing the latitude and longitude of your users can open up all kinds of possibilities in your apps. In an upcoming post, we’ll be discussing how you can use your user’s location to determine their local weather conditions and forecast. But for now, we’re going to focus on Part 1 of this two part tutorial: CoreLocation.

Apple’s done a great job of abstracting GPS, Cellular Triangulation, and Wifi Access Point location lookups into CoreLocation; making it extremely easy to determine the approximate location of your user regardless of their device and network connectivity. Additionally, Apple’s new iPhone Simulator finally supports CoreLocation as well. This significantly eases the process of testing your location code.

The first thing you’ll need to do is add the CoreLocation framework to your project. This is pretty straightforward. Command-Click on ‘Frameworks’ -> Add -> Existing Frameworks

Select ‘CoreLocation.framework’ and click ‘add’.

The class below implements the LocationManager delegate methods required to get the user’s location. You can just as easily implement the LocationManagerDelegate protocol in your AppDelegate or elsewhere in your App. Though I’ve found that having this class makes it super easy to drop in location support into new projects instead of having to cut/paste delegate methods (ugly). Anyway. Take a look:

//
//  LocationGetter.h
//  CoreLocationExample
//
//  Created by Matt on 9/3/10.
//  Copyright 2009 iCodeBlog. All rights reserved.
//
 
#import <uikit/UIKit.h>
#import <coreLocation/CoreLocation.h>
 
@protocol LocationGetterDelegate
@required
- (void) newPhysicalLocation:(CLLocation *)location;
@end
 
@interface LocationGetter : NSObject  {
    CLLocationManager *locationManager;
    id delegate;
}
 
- (void)startUpdates;
 
@property (nonatomic, retain) CLLocationManager *locationManager;
@property(nonatomic , retain) id delegate;
@end

Notice that we’re defining our own protocol with a method that takes the new CLLocation as a parameter. We’ll be implementing that delegate method in a minute. Now for the class

 
//  LocationGetter.m
//  CoreLocationExample
//
//  Created by Matt on 9/3/10.
//  Copyright 2009 iCodeBlog. All rights reserved.
//
 
#import "LocationGetter.h"
#import <coreLocation/CoreLocation.h>
 
@implementation LocationGetter
 
@synthesize locationManager, delegate;
BOOL didUpdate = NO;
 
- (void)startUpdates
{
    NSLog(@"Starting Location Updates");
 
    if (locationManager == nil)
        locationManager = [[CLLocationManager alloc] init];
 
    locationManager.delegate = self;
 
    // locationManager.distanceFilter = 1000;  // update is triggered after device travels this far (meters)
 
    // Alternatively you can use kCLLocationAccuracyHundredMeters or kCLLocationAccuracyHundredMeters, though higher accuracy takes longer to resolve
    locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
    [locationManager startUpdatingLocation];
}
 
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Your location could not be determined." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
    [alert show];
    [alert release];
}
 
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manage didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    if (didUpdate)
        return;
 
    didUpdate = YES;
    // Disable future updates to save power.
    [locationManager stopUpdatingLocation];
 
    // let our delegate know we're done
    [delegate newPhysicalLocation:newLocation];
}
 
- (void)dealloc
{
    [locationManager release];
 
    [super dealloc];
}
 
@end

CoreLocation gives you a few options for the accuracy of the user’s location. The more accurate the measurement, typically the longer it takes LocationManager to call it’s delegate method didUpdateToLocation. It’s just something to keep in mind when deciding what level of accuracy to use.

Next we need to actually invoke this code and start getting location updates. I usually do this in my AppDelegate’s didFinishLaunchingWithOptions, though you could also do it in viewDidLoad somewhere if you didn’t need to know the user’s location on app startup.

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 
    UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
        spinner.center = CGPointMake(self.viewController.view.frame.size.width / 2, self.viewController.view.frame.size.height / 2);
    [spinner startAnimating];
 
    [viewController.view addSubview:spinner];
 
    // get our physical location
    LocationGetter *locationGetter = [[LocationGetter alloc] init];
    locationGetter.delegate = self;
    [locationGetter startUpdates];
 
    // Add the view controller's view to the window and display.
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
 
    return YES;
}

Notice that I’ve set locationGetter’s delegate to self. So in your .h, make sure to add LocationGetterDelegate to the interface.

//
//  CoreLocationExampleAppDelegate.h
//  CoreLocationExample
//
//  Created by Matt Tuzzolo on 9/3/10.
//  Copyright iCodeBlog 2010. All rights reserved.
//
 
#import <uikit/UIKit.h>
#import "LocationGetter.h"
 
@class CoreLocationExampleViewController;
 
@interface CoreLocationExampleAppDelegate : NSObject  {
    UIWindow *window;
    CoreLocationExampleViewController *viewController;
    CLLocation *lastKnownLocation;
}
 
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet CoreLocationExampleViewController *viewController;
@property (nonatomic, retain) CLLocation *lastKnownLocation;
 
@end

I’ve also added a CLLocation *lastKnownLocation that we’ll use in our delegate method (which comes next):

# pragma mark -
# pragma mark LocationGetter Delegate Methods
 
- (void)newPhysicalLocation:(CLLocation *)location {
 
    // Store for later use
    self.lastKnownLocation = location;
 
    // Remove spinner from view
    for (UIView *v in [self.viewController.view subviews])
    {
        if ([v class] == [UIActivityIndicatorView class])
        {
            [v removeFromSuperview];
            break;
        }
    }
 
    // Alert user
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location Found" message:[NSString stringWithFormat:@"Found physical location.  %f %f", self.lastKnownLocation.coordinate.latitude, self.lastKnownLocation.coordinate.longitude] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
    [alert show];
    [alert release];
 
    // ... continue with initialization of your app
}

This last piece takes care of storing the location, removing the spinner, and firing off an alert. If this was your code, you’d probably want to re-enable any UI elements that you’ve disabled and let the user start using your app.

Now build and run your app and you should see:

That’s it!

Here’s the Example Project for the post.

For those of you who don’t know me yet, my name is Matt Tuzzolo (). This is my first iCodeBlog post. I hope you enjoyed it.

  • http://icode.dreamvision-soft.com/blog/?p=80 Adding Local Weather Conditions To Your App (Part 1/2: Implementing CoreLocation) | iCode

    [...] Original post on iCodeBlog [...]

  • Bil

    Awesome! I love where you are going with this! Can’t wait for the next installment!

  • http://blog.indieiphonedev.com/ Tim

    Great post. Now how do we get the weather information?

  • Bil

    *friendly bump* This is an awesome subject and I would love to see the rest of this! Well done again and looking forward to the rest.

  • http://brandontreb.com brandontreb

    Bil,

    Matt should have the next post in this series out next week. We now have 3 primary authors on iCodeblog.com and are alternating posts each week.

    Thanks for reading!

  • http://icodeblog.com/2010/09/29/adding-local-weather-conditions-to-your-app-part-22-accessing-googles-xml-weather-api/ Adding Local Weather Conditions To Your App (Part 2/2: Accessing Google’s XML Weather API) | iCodeBlog

    [...] If you’re lucky enough to already have the user’s zipcode or city and state, this should go very quickly for you. Otherwise, check out Part 1 (Integrating CoreLocation). [...]

  • http://icode.dreamvision-soft.com/blog/?p=86 Adding Local Weather Conditions To Your App (Part 2/2: Accessing Google’s XML Weather API) | iCode

    [...] If you’re lucky enough to already have the user’s zipcode or city and state, this should go very quickly for you. Otherwise, check out Part 1 (Integrating CoreLocation). [...]

  • http://www.nulldesign.pt/?p=690 Incluir Meteorologia numa App

    [...] Adding Local Weather Conditions To Your App (Part 1/2) [...]

  • http://www.ios4jailbreak.com/2010/09/adding-local-weather-conditions-to-your-app-part-22-accessing-google%e2%80%99s-xml-weather-api/ iOS4 Jailbreak » Adding Local Weather Conditions To Your App (Part 2/2: Accessing Google’s XML Weather API)

    [...] If you’re lucky enough to already have the user’s zipcode or city and state, this should go very quickly for you. Otherwise, check out Part 1 (Integrating CoreLocation). [...]

  • http://maniacdev.com/2010/10/tutorial-using-core-location-and-google-xml-weather-api/ Tutorial: Using Core Location And Google XML Weather API | iPhone, iOS 4, iPad SDK Development Tutorial and Programming Tips

    [...] tutorial can be found here: Adding Local Weather Conditions To Your App Part 1 Adding Local Weather Conditions To Your App Part [...]

  • http://www.edumobile.org/iphone/iphone-programming-tutorials/how-to-implement-core-location-and-the-google-xml-weather-api-on-the-iphone/ How To Implement Core Location And The Google XML Weather API on the iPhone | iPhone Tutorials & iPhone Development

    [...] Part 1 – Adding Local Weather Conditions, Part 1 Tutorial Part 2 – Adding Local Weather Conditions, Part [...]

  • http://iphonetuts.com/?p=107090 Adding Local Weather Conditions To Your App (Part 2/2: Accessing Google’s XML Weather API) | Iphone tutorials

    [...] If you’re lucky enough to already have the user’s zipcode or city and state, this should go very quickly for you. Otherwise, check out Part 1 (Integrating CoreLocation). [...]

  • http://ilovebbs.com wanghq

    Cool, better than implementing the delegate directly.

    BTW, here is a memory leak.

    LocationGetter *locationGetter = [[LocationGetter alloc] init];
    locationGetter.delegate = self;
    [locationGetter startUpdates];

  • http://blog.mbtheme.com/tutorial-using-core-location-and-google-xml-weather-api/ Tutorial: Using Core Location And Google XML Weather API | iPhone support Blog

    [...] tutorial can be found here: Adding Local Weather Conditions To Your App Part 1 Adding Local Weather Conditions To Your App Part [...]

  • moosc

    @wanghq
    Do you know how to fix this memory leak?

  • http://goldenhearted.co.cc Golden Hearted

    second post is online

  • http://difusi.com Michael Wright

    forgetting to add the @synthesize statement is one of the most common mistakes.

  • CPL

    Great demo Matt,
    Thanks for the help

  • Drew

    I’ve had problems with the memory leak as well… what am I forgetting to @synthesize, if that is indeed the problem?