I am completely new to iOS development so I may be doing this wrong but I have a class I am using to get coordinate gps data that I want to have as a generic class I can reuse in lots of apps. My problem is getting the data from the gps to properly display in other apps.
Here is my header file for the GPS class:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface LocationAwareness : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
}
#property(copy) NSString *longitude;
#property(copy) NSString *latitude;
#end
And here is the implementation:
#import "LocationAwareness.h"
#implementation LocationAwareness
#synthesize longitude;
#synthesize latitude;
- (id)init {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// Stops updating location if data has been updated within 10 minutes
if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 600) {
[locationManager stopUpdatingLocation];
float latitudedata = newLocation.coordinate.latitude;
latitude = [NSString stringWithFormat:#"%f", latitudedata];
float logitudedata = newLocation.coordinate.longitude;
longitude = [NSString stringWithFormat:#"%f", logitudedata];
}
}
#end
Now I can't seem to find anywhere that tells me how to get the latitude or longitude properties in another project. I have the header imported and have tried to store LocationAwareness.latitude into a variable that I can use but everything I store it in ends up blank. When I start my main class and aloc init a locationawareness object the gps fires up so I think its working but I don't seem to know enough about how this works to get everything in order. I've been searching the internet for hours. Anyone have an idea what I am doing wrong?
Well, this may or may not be causing the problem (it's quite likely), but a major problem is your init method.
The beginning should be:
self = [super init];
if (self) {
// Do your initializing as you did above.
}
return self;
edit:
I added your code with my update to a project and it works well.
In order to use this, you should do something like the following:
LocationAwareness *loc = [[LocationAwareness alloc] init];
// Give it some time to start updating the current location and then
// in a different function:
NSLog(#"%#", loc.latitude);
EDIT 2
Wherever you are using this, you will want to declare a property which stores it so that you can create it once and reference it many times. To do that, use the following code:
In the header for the object where you want to use this object, add this with the other properties:
#property (nonatomic, assign) LocationAwareness *location;
Then, towards the top of your implementation file (.m file) you should see other #synthesize lines, add this one:
#synthesize location;
Then, create the actual location instance that you want to use as per the example above:
self.location = [[LocationAwareness alloc] init];
Now give it some time to figure out your location and start providing updates. Then you can print the location like this:
NSLog(#"%#", self.location.latitude);
Related
First off, the disclaimer is I'm targeting iOS 5, so that very well may be the source of my issues, but if not...
I'm trying to write a simple class that manages location updates through CoreLocation. However, I see some pretty strange behavior. I have a custom class which basically wraps CLLocationManager and the delegate methods. This is the interface:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#protocol CLZipCodeFetcherDelegate
#optional - (void)didReceiveZipCode:(NSString *)zipCode;
#end
#interface CLZipCodeFetcher : NSObject <CLLocationManagerDelegate> {
id <CLZipCodeFetcherDelegate> delegate;
CLLocationManager *locationManager;
}
#property (strong, readwrite) id <CLZipCodeFetcherDelegate> delegate;
#property (strong, read write) CLLocationManager *locationManager;
- (void)getZipCode;
#end
and the implementation (ignore the zip code related stuff- that's what the class is eventually meant to do, but right now I'm just trying to get some coordinates back from CoreLocation):
#import "CLZipCodeFetcher.h"
#implementation CLZipCodeFetcher
#synthesize delegate, locationManager;
- (id) init {
self = [super init];
if (self != nil) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = 10.0f; // we don't need to be any more accurate than 10m
self.locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
self.locationManager.purpose = #"Retrieve zip code";
}
return self;
}
- (void)getZipCode {
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(#"Received location");
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"Location failed");
}
#end
And then I initialize an instance of the class in my view controller and call the method:
CLZipCodeFetcher *zipCodeFetcher = [[CLZipCodeFetcher alloc] init];
[zipCodeFetcher getZipCode];
Now, when I run this, the app takes a moment to load, and then pops up the alert dialog asking for permission to let the app use location services. However, as soon as it appears, it immediately disappears (too fast to let me hit the allow or deny button), and nothing happens (no delegate methods are called). If I then go into the Location Settings of the device, it indeed shows 'Off' for my app. When I turn it on manually from that screen and then go to try the app again, no alert dialog appears, but still nothing happens. Neither of my debug messages are logged. The behavior is the same on both the simulator and my iPhone 4.
So basically, anyone have any idea why? I've looked through all the similar threads, and many issues were related to memory management, but I don't think that'd be a problem here since ARC should be managing my CLLocationManager object, right?
P.S. Also, I did add the CoreLocation framework to my project, and I get no code errors or warnings, but is there anything else I need to do before using CoreLocation in my app?
ARC is deallocating your newly created object after the getZipCode method call.
I have not used ARC yet so I'm not sure of your syntax in the header (readwrite vs. read write).
But I would put an NSLog(#" my loc manager is %#", self.locationManager); inside of getZipCode just to make sure you've got one and it's not being released before it has a chance to do anything.
I need to read my position from GPS!
The problem is that i need to do out from the method
- (void)locationUpdate:(CLLocation *)location;
So... this is how i'm working:
in the .h file i have this
CLLocation *mylocation;
in the -viewDidLoad
mylocation = [[CLLocation alloc] init];
locationController = [[CLController alloc] init];
locationController.delegate = self;
[locationController.locationManager startUpdatingLocation];
then
- (void)locationUpdate:(CLLocation *)location {
mylocation = location;
}
and it works, if i use NSLog (on mylocation) i see my real location!
But... in another method (an IBAction connected with a UIButton) i want to use "mylocation"!
It's not working and i don't know why!
If, in this method, i try to do this
NSLog(#"%#", mylocation);
the console report this:
<+0.00000000, +0.00000000> +/- 0.00m (speed -1.00 mps / course -1.00) # 3/10/11 7:21:24 PM Central European Time
So the variable is empty!
Why??
PS= also in my IBAction i have, of course, this
mylocation = [[LCLocation alloc] init];
otherwise the app crashes!
This line:
mylocation = location;
Is setting mylocation's memory pointer to the one returned by the location manager, which later is getting released.
EDITED:
mylocation = [[CLLocation alloc] initWithLatitude:location.coordinate.latitude longitude:location.coordinate.longitude];
also in my IBAction i have, of course, this
mylocation = [[LCLocation alloc] init];
So you get zero values because you always overwrite your location value with newly created blank location - you should not do that.
The problem that makes your application crash is that in locationUpdate method you get autoreleased value, so in order to ensure that its valid outside of that method you must retain it. (and not forget to release old value). The easiest way to do that is create a property for myLocation ivar and access ivar using it:
// .h file
#property (nonatomic, retain) CLLocation *myLocation;
// .m
#synthesize myLocation;
...
- (void)locationUpdate:(CLLocation *)location {
self.mylocation = location;
}
- (void) dealloc{
[myLocation release];
myLocation = nil;
...
[super dealloc];
}
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.
fellas,
I am developing a application in which I need functionality to ask user for their location more than once, what happening is when user allowed it once to use his location and when he navigate to another section it's not asking him to get his location, it's taking it from already cached location.
is that possible to ask user multiple time for his approval to get his location?
Any help appreciated.
Cheers,
Amit
You don't need to get permission multiple times.
To begin getting updates, you call:
[locationManager startUpdatingLocation];
Until you call [locationManager stopUpdatingLocation] you will get continuous location updates.
So, you need to implement the delegate method to say what happens when you get a new location. This delegate method could do something as simple as save the location to a class variable for later use.
The delegate function you need to implement is:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {}
I should caution you here. It is battery intensive to constantly run the GPS (you'll kill the device in about 2.5 hours if you are requesting very accurate reading as fast as possible). So, what you should probably do is get a fix when the user turns the app on, and then call stopUpdatingLocation.
Then, in your app, have a "Locate Me" button, which would turn on the LocationManager, get a fix, and then turn off the LocationManager again. You might want to keep polling for a location until you get a good location.horizontalAccuracy
I suggest you implement an NSObject subclass, which implements the LocationManagerDelegate protocol. Then, this object would be shared across multiple view controllers. Here is a simple implementation of a central gpsController.
So, this would be gpsController.h:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface gpsController : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
CLLocation *lastReading;
}
- (id)init;
#property (nonatomic, retain) CLLocationManager *locationManager;
#property (nonatomic, retain) CLLocation *lastReading;
#end
And then the following is gpsController.m:
#import "gpsController.h"
#implementation gpsController
#synthesize locationManager, lastReading;
- (id)init {
if(self = [super init]) {
[[self locationManager] startUpdatingLocation];
self.lastReading = nil;
}
return self;
}
- (CLLocationManager *)locationManager {
if (locationManager) return locationManager;
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
locationManager.delegate = self;
return locationManager;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
self.lastReading = newLocation;
}
According to iPhone Programming: The Big Nerd Ranch Guide, CLLocationManagers return the cached, last found device location first. Their sample code bails out of locationManager:didUpdateToLocation:fromLocation if the didUpdateToLocation timestamp is more than 3 minutes old, assuming it to be from the cache. That seems a pretty long time between valid updates, but maybe only by doing some testing would one know.
Maybe you could persist the timestamp between messages to see if you're still being served location data from the cache, or increment a counter for each call to locationManager:didUpdateToLocation:fromLocation and only ever use odd numbered calls or some other increment...
I want to get my longitude and latitude on iPhone in objective C. Can any one guide me how to get these coordinates programmatically?
#import <Foundation/Foundation.h>
#class CLLocationManager;
#interface CLLocationController : NSObject {
CLLocationManager *locationManager;
}
#property (nonatomic, retain) CLLocationManager *locationManager;
#end
When i write above code is shows me following errors
/Hab/Folder/Classes/CLLocationController.m:10:30: error: CLLocationManager.h: No such file or directory
/Hab/Folder/Classes/CLLocationController.m:21: warning: receiver 'CLLocationManager' is a forward class and corresponding #interface may not exist
/Hab/Folder/Classes/CLLocationController.m:22: error: accessing unknown 'delegate' component of a property
Use the CLLocationManager, set an object as the delegate and start getting updates.
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
Then implement the delegate:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation*)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog([NSString stringWithFormat:#"%3.5f", newLocation.coordinate.latitude]);
NSLog([NSString stringWithFormat:#"%3.5f", newLocation.coordinate.longitude]);
}