I am building a rails-backed iphone app that uses AFNetworking to create posts at specific locations. So the post model has lat/lng parameters that should be filled in with the client's current location.
At this point, the posts can be made, but the lat/lng comes up as null.
In my (save:) method I pass a conditional to see if a location was found- this is what is failing i.e. "No Location" is logged.
- (void)save:(id)sender {
[self getLocation];
NSArray *locations;
CLLocation *location = [locations objectAtIndex:0];
Post *post = [[Post alloc] init];
post.content = self.contentTextView.text;
post.photoData = UIImagePNGRepresentation(self.imageView.image);
[self.view endEditing:YES];
ProgressView *progressView = [ProgressView presentInWindow:self.view.window];
if (location) {
[post savePostAtLocation:location withBlock:^(CGFloat progress) {
[progressView setProgress:progress];
} completion:^(BOOL success, NSError *error) {
[progressView dismiss];
if (success) {
[self.navigationController popViewControllerAnimated:YES];
} else {
NSLog(#"ERROR: %#", error);
}
}];
} else {
NSLog(#"No Location");
}
}
I have also attempted to implement a locationManager like so
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
[self getLocation];
}
-(CLLocation *) getLocation{
CLLocationManager * locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
self.locationManager.distanceFilter = 80.0f;
[locationManager startUpdatingLocation];
CLLocation * location = [locationManager location];
return location;
}
I think ideally I would implement the savePostAtlocation in the CLLocationManagerDelegate where I could pass in the locations array like this:
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations objectAtIndex:0 /* firstObject */];
if (location) {
[Post createPostAtLocation:location...
But I want to have the post created onSave so I am trying to identify the location but running into some problems..
How do I properly get the current location and pass it into the dictionary?
Any advice on this would be greatly appreciated. Thanks!
Looking at your code, I think you have a slight misunderstanding about how CLLocationManager is designed to work. It looks like you are trying to call [self getLocation] from inside locationManager:didUpdateLocations. This is not correct. Try something like this, inside your save method that is called when you press your button (I would remove the code that's currently in there while testing):
CLLocationManager * locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
self.locationManager.distanceFilter = 80.0f;
[locationManager startUpdatingLocation];
Then it will start generating location data. When that happens, the phone will automatically call locationManager:didUpdateLocations very rapidly. Then, in locationManager:didUpdateLocations you could use:
CLLocation * location = [manager location];
NSLog(#"%#", location);
To see your location data in the console.
What I have written here should get the phone generating location data for you. What you say about createPostAtLocation: in locationManager:didUpdateLocations is probably the correct way to go. When you get the location data, call [manager stopUpdatingLocation] to make the phone stop, then post the location data you got back to your server.
Related
How can I do the following please?
I have a button in my iPhone app that the user clicks to start GPS navigation. All I do when the button is clicked is get their location, and pass it to Google maps to do the rest.
However, as soon as I land on the screen where the button is, the application ask me the standard "This app would like to use your current location". But I dont want this to be asked as soon as I land on the screen. Instead, it should be asked when the button is clicked.
Here is how I handle the scenario in my views .m file:
- (void)viewDidLoad
{
self.locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
And then when the button is clicked. Also tried to put the code from viewDidLoad here as can be seen from the commented out section. This works in that I dont get asked the question when the view loads, but then the GPS does not work once button is clicked. I get an error message on the app screen saying "The app was unable to establish a route to the nearest road". And the "This app would like to access your current location" only flashes up on the screen briefly.
- (IBAction)gpsNavigation:(id)sender
{
/*
self.locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
*/
NSString *destAddress = #"52.269444, -9.708674";
NSString *url = [NSString stringWithFormat: #"http://maps.apple.com/maps?saddr=%f%f&daddr=%#",
locationManager.location.coordinate.latitude,
locationManager.location.coordinate.longitude,
[destAddress stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}
Please use commented code in gpsNavigation: method.
Your problem is that you get locationManager.location as soon as you call [locationManager startUpdatingLocation].
So your code can be as following.
- (IBAction)gpsNavigation:(id)sender
{
self.locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSString *destAddress = #"52.269444, -9.708674";
NSString *url = [NSString stringWithFormat: #"http://maps.apple.com/maps?saddr=%f%f&daddr=%#",
locationManager.location.coordinate.latitude,
locationManager.location.coordinate.longitude,
[destAddress stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
[locationManager stopUpdatingLocation];
}
As soon as you call [locationManager startUpdatingLocation] your app request locations and will ask the user for permission. So delay this call untill you need it (button pressed)
My application gets the user's location in the appDelegate and calls that location in the viewDidAppear method of some viewControllers. My problem is that the first time the viewController's load, there hasn't been enough time to get the user's location.
Here is my AppDelegate:
- (NSString *)getUserCoordinates
{
NSString *userCoordinates = [NSString stringWithFormat:#"latitude: %f longitude: %f",
locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
return userCoordinates;
}
- (NSString *)getUserLatitude
{
NSString *userLatitude = [NSString stringWithFormat:#"%f",
locationManager.location.coordinate.latitude];
return userLatitude;
}
- (NSString *)getUserLongitude
{
NSString *userLongitude = [NSString stringWithFormat:#"%f",
locationManager.location.coordinate.longitude];
return userLongitude;
}
Here is what I am using to call the location from the viewControllers:
- (void) viewDidAppear:(BOOL)animated
{
NSString *userLatitude =[(PDCAppDelegate *)[UIApplication sharedApplication].delegate
getUserLatitude];
NSString *userLongitude =[(PDCAppDelegate *)[UIApplication sharedApplication].delegate
getUserLongitude];
}
Anyone have any ideas on how to fix? Thanks so much!
Try to use global variables here. It will be updated as your location updates and you will have updated location cordinates all time.
-(void)didUpdateLocation // location update method of CLLocation Manager class
{
// assign current ordinates values to global variables.
}
Not sure why you posted the same question two times... but see my answer at your other post,
Pass Coordinates from locationManager in appDelegate to viewController
In short, you need to implement the delegate methods of CoreLocation, as those methods are called when a new location is found. In those delegate methods, fire off an NSNotification (which ViewControllers) subscribe to in order to get the new user's location.
I need a good tutorial in which user's current location (latitude,longitude,city,state,country) is found and updated from time to time as the location changes and displayed on the map kit with the blue icon zooming.
I did it by placing an MKMapView on view.xib and it shows current location of user (default on simulator :SanFransisco) with blue dot zooming only for the first time. But when I run the app next time it is not showing any blue dot zooming. Should I write any code? Till now I didn't write any code. Just placed a mapkit with Show UserLocation checked in xib. How can I get a blue dot ?
I also need to find nearby doctors from the userlocation and display in the same map with red coloured markers pointing.
Gone through google but confused a lot. Please suggest to me some good tutorials in this regard.
EDIT:
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.mapView setShowsUserLocation:YES];
[locationManager startUpdatingLocation];
[self queryGooglePlaces:#"doctor"];
}
-(void) queryGooglePlaces: (NSString *) googleType {
// https://developers.google.com/maps/documentation/places/#Authentication
NSString *url = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/search/json?location=%f,%f&radius=300&types=doctor&sensor=true&key=%#", coord.latitude, coord.longitude,kGOOGLE_API_KEY];
NSURL *googleRequestURL=[NSURL URLWithString:url];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL: googleRequestURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
//Here I'm getting array data as null because latitude and longitude are passed as 0.000 ..
How can I get both of them on viewDidLoad?
if you want to find the near doctor address you need to use "GOOGLE PLACE API"
//For user current location
CLLocationCoordinate2D location = [[[mapview userLocation] location] coordinate];
NSLog(#"Location found from Map: %f %f",location.latitude,location.longitude);
Check this link its good example of google place api
Add this Delegate method of ccl location manager
.h file
double currentLatitude;
double currentLongitude;
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
currentLatitude = newLocation.coordinate.latitude;
currentLongitude = newLocation.coordinate.longitude;
[self queryGooglePlaces:somestring];
}
-(void) queryGooglePlaces: (NSString *) googleType {
// https://developers.google.com/maps/documentation/places/#Authentication
NSString *url = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/search/json?location=%f,%f&radius=300&types=doctor&sensor=true&key=%#", currentLatitude , currentLongitude,kGOOGLE_API_KEY];
NSURL *googleRequestURL=[NSURL URLWithString:url];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL: googleRequestURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
pass the current latitude and longitude in your -(void) queryGooglePlaces: (NSString *) googleType { } method
I am trying to calculate distance from start using Core Location framework, but when i put the Application on an iPhone device, the data is not correct. Distance keeps on fluctuating and showing random data. Kindly help me out. Also, Altitude is showing zero.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
//Altitude
if(startingPoint==nil)
self.startingPoint=newLocation;
NSString *currentAltitude = [[NSString alloc] initWithFormat:#"%g",
newLocation.altitude];
heightMesurement.text=currentAltitude;
[currentAltitude release];
//Distance
if(startingPoint==nil)
self.startingPoint=newLocation;
//if(newLocation.horizontalAccuracy <= 100.0f) {
// [locationManager stopUpdatingLocation];
//}
//test start.......................................................
//startlocation
NSString *sp = [[NSString alloc]
initWithFormat:#"%f",startingPoint];
NSLog(#"\nStarting point=%#",startingPoint);
ssp.text=sp;
//endlocation
NSString *ep = [[NSString alloc]
initWithFormat:#"%f",newLocation];
NSLog(#"\nStarting point=%#",newLocation);
eep.text=ep;
//test end............................................................
CLLocationDistance mydistance=[newLocation distanceFromLocation:startingPoint];
NSString *tripString = [[NSString alloc]
initWithFormat:#"%f",mydistance];
distLabel.text=tripString;
[tripString release];
//test........................
[sp release];
[ep release];
}//Location Manager ends..
//Time interval of 3 sec....
-(void)locationUpdate:(NSTimer*)timer{
if(timer != nil) [timer invalidate];
[self.locationManager startUpdatingLocation];
}
As to why your altitude may be zero, please see this answer to a similar question.
This may just be a problem with your NSLog statements, but both the starting and ending points are printed out with NSLog statements that say
NSLog(#"\nStarting point=%#",
The way you seem to have scheduled a 3-second timer is not really the way iOS wants you to use CLLocationManager. The preferred way is to tell CLLocationManager what your location criterion are, and then just start it updating. You don't actually need to keep telling it to start updating every 3 seconds. You can just do it once, and then if you ever decide you don't need any more updates, then call
[locationManager stopUpdatingLocation];
If the OS has no new location information, it probably doesn't make sense to keep asking. It'll tell you when it has new location information, via locationManager:didUpdateToLocation:fromLocation. So, I would recommend starting the process more like this:
CLLocationManager* locationManager = [[CLLocationManager alloc] init];
if ([locationManager locationServicesEnabled]) {
Reachability* netStatus = [Reachability sharedReachability];
if (([netStatus internetConnectionStatus] != NotReachable) || ([netStatus localWiFiConnectionStatus] != NotReachable)) {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = 100.0; // 100 m, or whatever you want
[locationManager startUpdatingLocation];
} else {
// TODO: error handling
}
}
self.locMgr = locationManager;
[locationManager release];
The location manager will often deliver you multiple results, with increasing accuracy as it hones in on your location. If you're continually restarting it, I'm wondering if that's causing it problems.
in CLLocationManagerDelegate, when will the method be invoke: locationManager:didUpdateToLocation:fromLocation:
could you explain more detail, if possible could you explain with example? thanks very much
if my current location is changing(eg, I am on a train), does this method be invoked? if yes, how many times or how frequently it is be invoked?
if I stay at one place and not move, does this method be invoked? if yes, how many times or how frequently it is be invoked?
This method is called whenever your iOS device has moved past the distance filter you have set. For example if you set it to
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
The method will be called every time the device is moved.
A code example of this would be finding the coordinates then assigning those values to labels
- (void)viewDidLoad{
[super viewDidLoad];
altitudeLabel.text = #"0 ft";
ftOrM = YES;
// Note: we are using Core Location directly to get the user location updates.
// We could normally use MKMapView's user location update delegation but this does not work in
// the background. Plus we want "kCLLocationAccuracyBestForNavigation" which gives us a better accuracy.
//
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self; // Tells the location manager to send updates to this object
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
[self.locationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation: (CLLocation*)newLocation fromLocation:(CLLocation *)oldLocation {
tLatitude = [NSString stringWithFormat:#"%3.5f", newLocation.coordinate.latitude];
tLongitude = [NSString stringWithFormat:#"%3.5f", newLocation.coordinate.longitude];
/* the following returns 0 */
float distanceMeters;
float distanceFeet;
if (ftOrM == YES) {
distanceMeters = newLocation.altitude;
distanceFeet = distanceMeters * 3.2808399;
tAltitude = [NSString stringWithFormat:#"%.02f ft", distanceFeet];
altitudeLabel.text = tAltitude;
}
else {
tAltitude = [NSString stringWithFormat:#"%.02f m", newLocation.altitude];
NSLog(#"Altitude:");
NSLog(#"%#", tAltitude);
altitudeLabel.text = tAltitude;
NSLog(#"Altitude:");
NSLog(#"%#", tAltitude);
}
//[manager stopUpdatingLocation];
}
For the first one this method will invoked, and the frequency depends on the speed.
And if don't change your location then this method will not invoked.
And how much time your location is changing this method will call.