Updating location iPhone App - iphone

I'm trying to get the app to update the user's location as the user moves, and update POI based on his location. It doesn't work right now (the user's location stays the same even if he moves by a lot). Can anybody help me out?
- (void)viewDidLoad {
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
locationManager.distanceFilter = 1000;
[mapView removeAnnotations: mapView.annotations];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
homeCoordinate = newLocation.coordinate;
if (!home1Annotation) {
home1Annotation = [[MyMapAnnotation alloc] initWithCoordinate:homeCoordinate
title:#"Current Location"
];
[mapView addAnnotation:home1Annotation];
[self adjustMapZoom];
[self loadAndSortPOIs];
for (int j =0 ; j <5 ; j++){
[self displayPOIs];
}
}
}
My Map Annotation
#import "MyMapAnnotation.h"
#implementation MyMapAnnotation
#synthesize coordinate;
#pragma mark initializers
// designated initializer
-(id) initWithCoordinate:(CLLocationCoordinate2D)coordinateQ title:(NSString*) titleQ {
if ( self = [super init]) {
coordinate = coordinateQ;
title = titleQ;
[title retain];
}
return self;
}
-(void) dealloc {
[title release];
[super dealloc];
}
#pragma mark MKAnnotation implementation
-(NSString*) title { return title; }
-(NSString*) subtitle { return nil; }
#end

Two things go wrong:
1) ask for the highest accuracy: kCLLocationAccuracyBest instead of kCLLocationAccuracyHundredMeters. Don't set distanceFilter or set it to zero.
2) in didUpdateToLocation, add a line
NSLog(#"Location update: %#",newLocation);
and watch logfile output. Your if statement makes that the code block below is only run once. I would expect an else block, which will update the POI location in case the home1Annotation already exists. Something like:
} else {
[MyMapAnnotation setCoordinate:homeCoordinate];
}
(but I do not know your class MyMapAnnotation so this is guessing)

There shouldn't be any problems, all will work, but in your case next call about user location changed will be called when user will cane their place from recent detection on distance of 1 kilometer as you specified by this code locationManager.distanceFilter = 1000;

Related

custom Location Manager class using CLLocationManager

I'm pretty new to iOS development (my first app) and I faced this issue.
I have an iPhone app that should get user's current location in multiple ViewControllers upon user button touch. To prevent redundant code (implementing locationManager:didFailWithError, locationManager:didUpdateToLocation:fromLocation, etc. multiple times in different view controllers) I decided to create a custom class called LocationManager:
LocationManager.h
#interface LocationManager : NSObject <CLLocationManagerDelegate> {
#private
CLLocationManager *CLLocationManagerInstance;
id<LocationManagerAssigneeProtocol> assignee;
}
-(void) getUserLocationWithDelegate:(id) delegate;
LocationManager.m
#implementation LocationManager
-(id)init {
self = [super init];
if(self) {
CLLocationManagerInstance = [[CLLocationManager alloc] init];
CLLocationManagerInstance.desiredAccuracy = kCLLocationAccuracyBest;
CLLocationManagerInstance.delegate = self;
}
return self;
}
-(void) getUserLocationWithDelegate:(id) delegate {
if([CLLocationManager locationServicesEnabled]) {
assignee = delegate;
[CLLocationManagerInstance startUpdatingLocation];
}
}
#pragma CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
...
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
[CLLocationManagerInstance stopUpdatingLocation];
[assignee didUpdateToLocation:newLocation];
}
and I have a protocol called LocationManagerAssigneeProtocol that my ViewControllers implement
#protocol LocationManagerAssigneeProtocol <NSObject>
#required
-(void) didUpdateToLocation:(CLLocation *) location;
#end
and in my viewcontroller where needed
- (IBAction)getMyLocation:(id)sender {
[locationMgr getUserLocationWithDelegate:self];
}
This code works perfectly, however, I have a feeling that I'm violating some design patterns here by letting LocationManager be able to call a function of the class that itself initiated a call to Location Manager. On the other hand, I don't want to go with implementing CLLocationManagerDelegate for all my viewcontrollers that are supposed to work with locations.
Are there any better solution to this issue?
I agree with #CarlVeazey on this one. Delegate are great for a 1 to 1 relationship existing at any one time, however in your case it seems that you may need multiple viewControllers to respond to location events at any given time. So just remove anything related to your delegate and its associated protocol.
I'd probably make LocationManager class a singleton and modify the methods for updating:
+(LocationManager *)sharedInstance
{
static LocationManager *_sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
-(void)getUserLocation
{
if ([CLLocationManager locationServicesEnabled])
[CLLocationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
[CLLocationManagerInstance stopUpdatingLocation];
[[NSNotificationCenter defaultCenter] postNotificationWithName:#"LocationManagerDidUpdateLocation" object:newLocation];
}
... Then any viewController that needs to use this class would have something like:
-(void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserverForName:#"LocationManagerDidUpdateLocation" object:self queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
CLLocation *location = note.object;
...
}];
}
-(IBAction)getMyLocation:(id)sender {
[[LocationManager sharedInstance] getUserLocation];
}
Hope that helps and makes sense.

CLLocationManager in background thread

I am doing one application.In that i am using the CLLocationManager Class for getting the updated location latitude and longitude details.But i need to use this CLLocationManager in sepaate thread .I written my code like below.
- (void)viewDidLoad
{
[NSThread detachNewThreadSelector:#selector(fetch) toTarget:self withObject:nil];
}
-(void)fetch
{
manager=[[CLLocationManager alloc]init];
manager.delegate=self;
manager.distanceFilter=kCLDistanceFilterNone;
manager.desiredAccuracy = kCLLocationAccuracyBest;
[manager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"%f",newLocation.coordinate.latitude);
lbl.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.longitude];
}
.But this delegate method is not fired when i run this code.So please guide me how to get the location updates in separate thread.
The methods of your delegate object are called from the thread in which you started the corresponding location services. That thread must itself have an active run loop, like the one found in your application’s main thread. ——from apple document
Could you please tried with this.
dispatch_async(newThread, ^(void) {
[self fetch];
});
hope you'll get solved problem.
in .h file
MainView *ctl;
NSMutableDictionary *dictSubPoses;
- (id)initWithCtl:(MainView*)_ctl;
in .m file
- (id)initWithCtl:(MainView*)_ctl
{
if(self = [super init])
{
ctl = _ctl; //[_ctl retain];
}
return self;
}
- (void)main
{
[ctl performSelector:#selector(yourMethod) withObject:dictSubPoses];
}
in .h file
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
//Set Delegate
CLLocationManagerDelegate
// Declare
CLLocationManager *locationManager;
in .m file
-(void)ViewDidLoad
{
locationupadate=YES;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = 100.0f;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if(locationupadate)
{
NSLog(#"%f",newLocation.coordinate.latitude);
lbl.text=[NSString stringWithFormat:#"%f",newLocation.coordinate.longitude];
}

CLLocationManager startUpdatingLocation using a UIButton

This is the first time I am using CLLocationManager. I am not sure if i am doing the right thing. Correct me if i am wrong.
I initialize the locationManager in my viewDidLoad Method and tell the locationManager to startUpdatingLocation in the same method.
When the delegate receives
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
[locationManager stopUpdatingLocation];
//do stuff with the coordinates
}
to avoid repeated calls to this delegate method.
I have a UIButton where users can click to update the location
//called by user action
-(IBAction)updateLocation{
//start updating delegate
locationManager.delegate=self;
[locationManager startUpdatingLocation];
}
However when the location changes and when I click the UIbutton, the location coordinates donot change at all. :(
What am i doing wrong? Is this the right of doing or should i not stop the locationManager at all ?
Help would be appreciated.
CLLocationManager caches your last location and returns it as soon as you call -startUpdatingLocation. So, you are starting updates, receiving the old location, and then stopping updates.
This isn't how -startUpdatingLocation/-stopUpdatingLocation are meant to be used. As I asked above, what's wrong with calling the delegate method multiple times? If you only want to get the location when the user taps a button, leave the CLLocationManager updating, and just check CLLocationManger's location property when the user taps your button.
If the reason you're trying to avoid multiple calls to the delegate method is because you're worried about power consumption, etc., adjust the desiredAccuracy property of the CLLocationManager with something like: locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters.
All told, it might look something like this...
.h file:
#interface YourController : NSObject <CLLocationManagerDelegate>
#property (nonatomic, retain) CLLocationManager *locationMgr;
#property (nonatomic, retain) CLLocation *lastLocation;
- (IBAction)getNewLocation:(id)sender;
#end
.m file:
#interface YourController
#synthesize locationMgr = _locationMgr;
#synthesize lastLocation = _lastLocation;
- (id)init
{
if (self = [super init]) {
self.locationMgr = [[CLLocationManager alloc] init];
self.locationMgr.desiredAccuracy = kCLLocationAccuracyBest;
self.locationMgr.delegate = self;
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if (!self.lastLocation) {
self.lastLocation = newLocation;
}
if (newLocation.coordinate.latitude != self.lastLocation.coordinate.latitude &&
newLocation.coordinate.longitude != self.lastLocation.coordinate.longitude) {
self.lastLocation = newLocation;
NSLog(#"New location: %f, %f",
self.lastLocation.coordinate.latitude,
self.lastLocation.coordinate.longitude);
[self.locationMgr stopUpdatingLocation];
}
}
- (IBAction)getNewLocation:(id)sender
{
[self.locationMgr startUpdatingLocation];
NSLog(#"Old location: %f, %f",
self.lastLocation.coordinate.latitude,
self.lastLocation.coordinate.longitude);
}
- (void)dealloc
{
[self.locationMgr release];
self.locationMgr = nil;
[self.lastLocation release];
self.lastLocation = nil;
[super dealloc];
}
#end
Am assuming you have included #import <CoreLocation/CoreLocation.h> framework to being with. This is the way you start getting location updates.
CLLocationManager *locationMgr = [[CLLocationManager alloc] init];
locationMgr.desiredAccuracy = kCLLocationAccuracyBest;
locationMgr.delegate = self;
[locationMgr startUpdatingLocation];
You are correct here. After this you start getting location updates, here in this delegate-
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
// Handle location updates
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
// Handle error
}

Capturing current location and calculating distance

I've been looking at this for a while. I've found plenty of posts and looked at the documentation but I'm having trouble getting it working. I have core location implemented, and its working with no problems i.e.
NSLog(#"Description: %#\n", [newLocation description]);
The description details are displayed in the log.
I want to capture the current location when the user taps on a button and as they start to move recapture their location intermittently. Using this information I want to calculate the distance between the starting point and the current point.
I know I can use the following:
CLLocationDistance distance = [myLocation distanceFromLocation:restaurantLocation]
to calculate the distance but I'm not sure how to capture the current location.
If anyone could post some sample code that would be great. I close to getting this working, just need a final push over the line.
Regards,
Stephen
Part 2: Since the original post, I've made a bit of progess. Details posted below:
#import "MyCLController.h"
#implementation MyCLController
#synthesize locationManager;
#synthesize delegate;
- (id) init {
self = [super init];
if (self != nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self; // send loc updates to myself
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
[self.delegate locationUpdate:newLocation];
CLLocation *item1 = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
CLLocation *item2 = [[CLLocation alloc] initWithLatitude:oldLocation.coordinate.latitude longitude:oldLocation.coordinate.longitude];
int meters = [item1 getDistanceFrom:item2];
NSLog(#"Distance-d: %d", meters);
[item1 release];
[item2 release];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
[self.delegate locationError:error];
}
- (void)dealloc {
[self.locationManager release];
[super dealloc];
}
#end
Am I right to calculate the distance here or should I be doing it in NewWorkoutViewController.m, in the locationUpdate method ?
You set a delegate on your location manager which will be called when the location changes. You can control (indirectly) how often it gets called by specifing a distance filter so that you will only get a callback if the location has moved at least that amount.

how to get GPS Coordinates in iphone using Objective C

i want to get the GPS coordinates from iphone and send these GPS coordinates to web service. This web service, will take my GPS Coordinates and send me the location of the nearest ATM, from the current location.
now i want to do this in 2 phases.
First phase , i want to just send the GPS Coordinates to web service, and in return i want the address of the ATM location.
Second phase , i want to point this ATM on the MAP displayed in iphone app.
I have the web service developed, which take 2 input parameters : lat and longi.
and returns me the address of the ATM location in a string format.
To start with Phase 1 : Please help me with how to get the GPS cordinates and send it to the web service.
so that i can just display the address in string format(Result i get from web service) on the view.
Add Core Location to your project:
Highlight the application target.
Click on the Build Phases tab and expand the Link Binary with Libraries section.
Then click the + button and choose the CoreLocation framework.
Header File (.h)
Note the use of the delegate!
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#class DetailViewController;
#interface MasterViewController : UITableViewController<CLLocationManagerDelegate>
#property (nonatomic, retain) CLLocationManager *locationManager;
#end
Implementation File (.m)
#import "MasterViewController.h"
#implementation MasterViewController
#pragma mark - Properties
#synthesize locationManager;
#pragma mark - Methods
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
[self initializeMenuItems];
if (self.locationManager == nil)
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy =
kCLLocationAccuracyNearestTenMeters;
self.locationManager.delegate = self;
}
[self.locationManager startUpdatingLocation];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// Turn off the location manager to save power.
[self.locationManager stopUpdatingLocation];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1. Get the current location
CLLocation *curPos = locationManager.location;
NSString *latitude = [[NSNumber numberWithDouble:curPos.coordinate.latitude] stringValue];
NSString *longitude = [[NSNumber numberWithDouble:curPos.coordinate.longitude] stringValue];
NSLog(#"Lat: %#", latitude);
NSLog(#"Long: %#", longitude);
}
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"%#", #"Core location has a position.");
}
- (void) locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
NSLog(#"%#", #"Core location can't get a fix.");
}
#end
Add CoreLocation framework to your project
Create and setup an instance of CLLocationManager (e.g. set desiredAccuracy property)
Set a delegate to your location manager
In your delegate implement 2 methods: -didFailWithError and -didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
Call -startUpdatingLocation on your location manager.
In didUpdate method you get all updates in your current location and can also check if the coordinates you get is valid for you (check horizontalAccuracy and timeStamp properties)
This sample code from apple (edit: link moved) : https://developer.apple.com/library/content/samplecode/LocateMe/
You have to ask user permission, adding this property in you plist : NSLocationWhenInUseUsageDescription
then, here is basically how apple does in a viewController (copied from link above) :
/*
Copyright (C) 2014 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
*/
#import "GetLocationViewController.h"
#import "LocationDetailViewController.h"
#import "SetupViewController.h"
#import "CLLocation+Strings.h"
#interface GetLocationViewController () <SetupViewControllerDelegate, CLLocationManagerDelegate>
#property (nonatomic, weak) IBOutlet UIButton *startButton;
#property (nonatomic, weak) IBOutlet UILabel *descriptionLabel;
#property (nonatomic, weak) IBOutlet UITableView *tableView;
#property (nonatomic, strong) SetupViewController* setupViewController;
#property (nonatomic, copy) NSString *stateString;
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) NSDateFormatter *dateFormatter;
#property (nonatomic, strong) NSMutableArray *locationMeasurements;
#property (nonatomic, strong) CLLocation *bestEffortAtLocation;
#end
#pragma mark -
#implementation GetLocationViewController
- (void)viewDidLoad {
[super viewDidLoad];
_locationMeasurements = [NSMutableArray array];
}
- (NSDateFormatter *)dateFormatter {
if (_dateFormatter == nil) {
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[_dateFormatter setTimeStyle:NSDateFormatterLongStyle];
}
return _dateFormatter;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UINavigationController *nv = segue.destinationViewController;
_setupViewController = nv.viewControllers[0];
self.setupViewController.delegate = self;
}
#pragma mark - Actions
// The reset method allows the user to repeatedly test the location functionality.
// In addition to discarding all of the location measurements from the previous "run",
// it animates a transition in the user interface between the table which displays location
// data and the start button and description label presented at launch.
//
- (void)reset {
_bestEffortAtLocation = nil;
[self.locationMeasurements removeAllObjects];
// fade in the rest of the UI and fade out the table view
[UIView animateWithDuration:0.6f animations:^(void) {
self.startButton.alpha = 1.0;
self.descriptionLabel.alpha = 1.0;
self.tableView.alpha = 0.0;
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
} completion:^(BOOL finished) {
if (finished) {
//..
}
}];
}
#pragma mark - Location Manager Interactions
// This method is invoked when the user hits "Done" in the setup view controller.
// The options chosen by the user are passed in as a dictionary. The keys for this dictionary
// are declared in SetupViewController.h.
//
- (void)setupViewController:(SetupViewController *)controller didFinishSetupWithInfo:(NSDictionary *)setupInfo {
self.startButton.alpha = 0.0;
self.descriptionLabel.alpha = 0.0;
self.tableView.alpha = 1.0;
// Create the core location manager object
_locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
self.locationManager.desiredAccuracy = [setupInfo[kSetupInfoKeyAccuracy] doubleValue];
// Once configured, the location manager must be "started"
//
// for iOS 8, specific user level permission is required,
// "when-in-use" authorization grants access to the user's location
//
// important: be sure to include NSLocationWhenInUseUsageDescription along with its
// explanation string in your Info.plist or startUpdatingLocation will not work.
//
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
[self performSelector:#selector(stopUpdatingLocationWithMessage:)
withObject:#"Timed Out"
afterDelay:[setupInfo[kSetupInfoKeyTimeout] doubleValue]];
self.stateString = NSLocalizedString(#"Updating", #"Updating");
[self.tableView reloadData];
}
// We want to get and store a location measurement that meets the desired accuracy.
// For this example, we are going to use horizontal accuracy as the deciding factor.
// In other cases, you may wish to use vertical accuracy, or both together.
//
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// store all of the measurements, just so we can see what kind of data we might receive
[self.locationMeasurements addObject:newLocation];
// test the age of the location measurement to determine if the measurement is cached
// in most cases you will not want to rely on cached measurements
//
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (locationAge > 5.0) {
return;
}
// test that the horizontal accuracy does not indicate an invalid measurement
if (newLocation.horizontalAccuracy < 0) {
return;
}
// test the measurement to see if it is more accurate than the previous measurement
if (self.bestEffortAtLocation == nil || self.bestEffortAtLocation.horizontalAccuracy > newLocation.horizontalAccuracy) {
// store the location as the "best effort"
_bestEffortAtLocation = newLocation;
// test the measurement to see if it meets the desired accuracy
//
// IMPORTANT!!! kCLLocationAccuracyBest should not be used for comparison with location coordinate or altitidue
// accuracy because it is a negative value. Instead, compare against some predetermined "real" measure of
// acceptable accuracy, or depend on the timeout to stop updating. This sample depends on the timeout.
//
if (newLocation.horizontalAccuracy <= self.locationManager.desiredAccuracy) {
// we have a measurement that meets our requirements, so we can stop updating the location
//
// IMPORTANT!!! Minimize power usage by stopping the location manager as soon as possible.
//
[self stopUpdatingLocationWithMessage:NSLocalizedString(#"Acquired Location", #"Acquired Location")];
// we can also cancel our previous performSelector:withObject:afterDelay: - it's no longer necessary
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(stopUpdatingLocationWithMessage:) object:nil];
}
}
// update the display with the new location data
[self.tableView reloadData];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
// The location "unknown" error simply means the manager is currently unable to get the location.
// We can ignore this error for the scenario of getting a single location fix, because we already have a
// timeout that will stop the location manager to save power.
//
if ([error code] != kCLErrorLocationUnknown) {
[self stopUpdatingLocationWithMessage:NSLocalizedString(#"Error", #"Error")];
}
}
- (void)stopUpdatingLocationWithMessage:(NSString *)state {
self.stateString = state;
[self.tableView reloadData];
[self.locationManager stopUpdatingLocation];
self.locationManager.delegate = nil;
UIBarButtonItem *resetItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Reset", #"Reset")
style:UIBarButtonItemStylePlain
target:self
action:#selector(reset)];
[self.navigationItem setLeftBarButtonItem:resetItem animated:YES];
}
#pragma mark - UITableViewDataSource
// The table view has three sections. The first has 1 row which displays status information.
// The second has 1 row which displays the most accurate valid location measurement received.
// The third has a row for each valid location object received
// (including the one displayed in the second section) from the location manager.
//
- (NSInteger)numberOfSectionsInTableView:(UITableView *)table {
return (self.bestEffortAtLocation != nil) ? 3 : 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *headerTitle = nil;
switch (section) {
case 0: {
headerTitle = NSLocalizedString(#"Status", #"Status");
break;
}
case 1: {
headerTitle = NSLocalizedString(#"Best Measurement", #"Best Measurement");
break;
}
default: {
headerTitle = NSLocalizedString(#"All Measurements", #"All Measurements");
break;
}
}
return headerTitle;
}
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
NSInteger numRows = 0;
switch (section) {
case 0: {
numRows = 1;
break;
}
case 1: {
numRows = 1;
break;
}
default: {
numRows = self.locationMeasurements.count;
break;
}
}
return numRows;
}
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
switch (indexPath.section) {
case 0: {
// The cell for the status row uses the cell style "UITableViewCellStyleValue1", which has a label on the left side of the cell with left-aligned and black text; on the right side is a label that has smaller blue text and is right-aligned. An activity indicator has been added to the cell and is animated while the location manager is updating. The cell's text label displays the current state of the manager.
static NSString * const kStatusCellID = #"StatusCellID";
static NSInteger const kStatusCellActivityIndicatorTag = 2;
UIActivityIndicatorView *activityIndicator = nil;
cell = [table dequeueReusableCellWithIdentifier:kStatusCellID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kStatusCellID];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
CGRect frame = activityIndicator.frame;
frame.origin = CGPointMake(290.0, 12.0);
activityIndicator.frame = frame;
activityIndicator.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
activityIndicator.tag = kStatusCellActivityIndicatorTag;
[cell.contentView addSubview:activityIndicator];
} else {
activityIndicator = (UIActivityIndicatorView *)[cell.contentView viewWithTag:kStatusCellActivityIndicatorTag];
}
cell.textLabel.text = self.stateString;
if ([self.stateString isEqualToString:NSLocalizedString(#"Updating", #"Updating")]) {
if (activityIndicator.isAnimating == NO) {
[activityIndicator startAnimating];
}
} else {
if (activityIndicator.isAnimating) {
[activityIndicator stopAnimating];
}
}
break;
}
case 1: {
// The cells for the location rows use the cell style "UITableViewCellStyleSubtitle", which has a left-aligned label across the top and a left-aligned label below it in smaller gray text. The text label shows the coordinates for the location and the detail text label shows its timestamp.
static NSString * const kBestMeasurementCellID = #"BestMeasurementCellID";
cell = [table dequeueReusableCellWithIdentifier:kBestMeasurementCellID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kBestMeasurementCellID];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
cell.textLabel.text = self.bestEffortAtLocation.localizedCoordinateString;
cell.detailTextLabel.text = [self.dateFormatter stringFromDate:self.bestEffortAtLocation.timestamp];
break;
}
default: {
// The cells for the location rows use the cell style "UITableViewCellStyleSubtitle", which has a left-aligned label across the top and a left-aligned label below it in smaller gray text. The text label shows the coordinates for the location and the detail text label shows its timestamp.
static NSString * const kOtherMeasurementsCellID = #"OtherMeasurementsCellID";
cell = [table dequeueReusableCellWithIdentifier:kOtherMeasurementsCellID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kOtherMeasurementsCellID];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
CLLocation *location = self.locationMeasurements[indexPath.row];
cell.textLabel.text = location.localizedCoordinateString;
cell.detailTextLabel.text = [self.dateFormatter stringFromDate:location.timestamp];
break;
}
}
return cell;
}
#pragma mark - UITableViewDelegate
// Delegate method invoked before the user selects a row.
// In this sample, we use it to prevent selection in the first section of the table view.
//
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
return (indexPath.section == 0) ? nil : indexPath;
}
// Delegate method invoked after the user selects a row. Selecting a row containing a location object
// will navigate to a new view controller displaying details about that location.
//
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
CLLocation *location = self.locationMeasurements[indexPath.row];
LocationDetailViewController *detailVC = [[LocationDetailViewController alloc] initWithStyle:UITableViewStyleGrouped];
detailVC.location = location;
[self.navigationController pushViewController:detailVC animated:YES];
}
#end
Import CoreLocation framework to app
import CoreLocation/CoreLocation.h librarie to ViewController
edit ViewController header file
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface EMViewController : UIViewController <CLLocationManagerDelegate>{
CLLocationManager *locationManager;
}
#end
initialize locationManager in ViewController implementation
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
NSLog(#" lat: %f",locationManager.location.coordinate.latitude);
NSLog(#" lon: %f",locationManager.location.coordinate.longitude);
[locationManager stopUpdatingLocation];
}