MapKit - didUpdateToLocation called but userLocation not updated - iphone

I have a MKMapView configured like so:
mapView = [[MKMapView alloc] init];
[mapView setMapType:MKMapTypeStandard];
[mapView setShowsUserLocation:YES];
[mapView setDelegate:self];
I then initialize a CLLocationManager and call startUpdatingLocation.
I am using iSimulate to send the GPS data from my phone, to the simulator, which seems to be working since the CLLocationManager delegate method is invoked with my correct GPS coordinates. However the MKMapView never moves the blue dot away from Cupertino.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(#"Did Update Location = %f / %f", [newLocation coordinate].latitude, [newLocation coordinate].longitude);
NSLog(#"Current User Location = %f / %f", [[mapView userLocation] coordinate].latitude, [[mapView userLocation] coordinate].longitude);
}
The above method outputs the following:
>>> Did Update Location = 40.740100 / -73.989900 # Correct
>>> Current User Location = 37.331693 / -122.030457 # Cupertino... Incorrect
Even if I manually update the userLocation's coordinate using:
[[mapView userLocation] setCoordinate:[newLocation coordinate]];
The dot still just sits on Cupertino. Am I missing something?

The problem with CLLocation manger is that is caches the old location and some time it returns the old location. To get a new location just check the time stamp of the CLLocation object if it is older than the time limit then ignore this location
-(void) locationManager:(CLLocationManager*)manager
didUpdateToLocation:(CLLocation*)newLocation
fromLocation:(CLLocation*) oldLocation
{
NSDate* time = newLocation.timestamp;
NSTimeInterval timePeriod = [time timeIntervalSinceNow];
if(timePeriod < 2.0 ) { //usually it take less than 0.5 sec to get a new location but you can use any value greater than 0.5 but i recommend 1.0 or 2.0
[manager stopUpdatingLocation];
// process the location
} else {
// skip the location
}
}

The dot still just sits on Cupertino. Am I missing something?
Are you testing this on the simulator? Note that in the simulator, the location dot always remains in Cupertino. Try it on a device - maybe you don't have a bug at all!

Related

path tracing on map in ios

Some one help me out please I am stuck on it from last few days...
My task is here.
In my app i need to integrate the map, as it open it should shows the current user position, as i pressed start button while walking it starts tracing path from the position where i pressed start button till the position i pressed stop.the distance covered in this interval should be traced turn by turn navigation and also wann to collect start and stop position coordinates to calculate distance.
i have added map kit framework, core location frame work, also added map view,and also implemented method to show current user position . now
here is my code
-(void)startSignificantChangeUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == self.locatioManager)
{
self.locatioManager = [[CLLocationManager alloc] init];
self.locatioManager.delegate = self;
[self.locatioManager startMonitoringSignificantLocationChanges];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// If it's a relatively recent event, turn off updates to save power
CLLocation* location = [locations lastObject];
NSDate* eventDate = location.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 15.0) {
// If the event is recent, do something with it.
NSLog(#"latitude %+.6f, longitude %+.6f\n",location.coordinate.latitude,location.coordinate.longitude);
}
MKCoordinateRegion ref=MKCoordinateRegionMakeWithDistance([location coordinate], 250,250);
[self.myMapView setRegion:ref animated:YES];
}
Please guide me from here to trace path, and can collect coordinates also .

How Can I Get Current Location on iOS? [duplicate]

This question already has answers here:
how to get the current location position in map on iphone
(2 answers)
Closed 9 years ago.
I can't get current location. When I launch my app in different place, App can get last location. But I don't want to last location. If you close the app and restart it, now app can get current location. How can I get current location even if it is first launch of application?
- (void)viewDidLoad
{
[super viewDidLoad];
[locationManager startUpdatingLocation];
self.mapView.delegate = self;
[self.mapView setShowsUserLocation:YES];
locationManager.delegate=self;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyBest;
locationManager.distanceFilter=kCLDistanceFilterNone;
location = [locationManager location];
CLLocationCoordinate2D coord;
coord.longitude = location.coordinate.longitude;
coord.latitude = location.coordinate.latitude;
lat = coord.latitude;
longt = coord.longitude;
}
You are doing [locationManager startUpdatingLocation]; before setting its delegate
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.desiredAccuracy=kCLLocationAccuracyBest;
locationManager.distanceFilter=kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
And implement its delegate method
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
}
You should read the documentation provided in the Location Awareness Programming Guide.
Specifically, when you ask for the current location, the system returns the last known location right away so you can do something useful with it. If you don't care about past locations, you can discard it and only use more recent location information by looking at the timestamp property of the CLLocation returned to determine how recent it is.
You should really read the CLLocationManager documentation.
Wat you are doing will not work, since it will take some time determine the device location.
Therefor you will need to wait until the CLLocationManager notifies you that a location has been determent.
You will need to implement the CLLocationManagerDelegate which will tell you if a location is determent or if the location determination failed.
Also you should also check if location can be determent with:
if ([CCLocationManager locationServicesEnabled]) {
// The location services are available.
}
You should also check wether you are authorize to use the location services with [CCLocationManager authorizationStatus].

CLLocationManager strange behavior

I am using location manager to get user location when he/she presses a button.
I just need that exat time location, so I turn off the updates after I get the location.
The thing if that the location I am getting id 0 lat 0 lng at the first time.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
lat = newLocation.coordinate.latitude;
lng = newLocation.coordinate.longitude;
[locationManager stopUpdatingLocation];
NSLog(#"New Latlng: %f x %f", lat, lng);
}
When the user presses the button I call: [locationManager startUpdatingLocation];
And right after that I send the location to my server [self sendData]. But the location is zero.
At my -sendData method I added an NSLog to track down what was going on and I realized that I was sending the data to the server before the -locationManager:didUpdateToLocation gets called...
2012-04-02 16:06:24.225 MyApp[2892:707] ---- Data sent to server ----
2012-04-02 16:06:25.167 MyApp[2892:707] Nova Latlng: -23.003582 x -43.316311
I tried this but it didnt work as expected either:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[locationManager startUpdatingLocation];
dispatch_async(dispatch_get_main_queue(), ^{
[self sendData];
});
});
How to make the [self sendData] wait until I have the lat and lng variables properly filled?
Why dont you make that call right after you stopUpdatingLocation ?
Put this code
dispatch_async(dispatch_get_main_queue(), ^{
[self sendData];
});
in didUpdateToLocation: after
[locationManager stopUpdatingLocation];
That should do it. The Location Manager updates come asynchronously, so you have to wait until there is something to process before you try to do anything with the data.

CoreLocation startMonitoringRegion not firing didenterregion /didexitregion delegates

i cant seem to get any of the didenterregion/didexitregion delegates firing , been stuck for 2 days on it
im using xcode4.2 with ios5 sdk and location simulation,
has anyone any luck getting this to work? is a 100m radius too small?(ive tried 1000 doesnt work too) or is there something wrong with my code
checked also with normal location updating and user location indeed enters region. could not find an answer anywhere as well
MainViewController(also CLLocationManagerDelegate)'s ViewDidLoad method:
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.showsUserLocation = YES;
mapView.mapType = MKMapTypeStandard;
mapView.delegate = self;
[self.view addSubview:mapView];
MKCoordinateRegion region;// = {{0.0,0.0},{0.0,0.0}};
MKCoordinateSpan span;
span.latitudeDelta = 0.02;
span.longitudeDelta = 0.02;
CLLocationCoordinate2D coordinates =CLLocationCoordinate2DMake(1.34537, 103.84515);
region.span = span;
region.center = coordinates;
[mapView setRegion:region animated:TRUE];
[mapView regionThatFits:region];
if (locationManager==nil){
locationManager = [[CLLocationManager alloc] init];
}
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
self.locationManager.delegate =self;
if ([CLLocationManager regionMonitoringAvailable]){
NSLog(#"regionMonitoring available");
CLRegion* region3 = [[CLRegion alloc] initCircularRegionWithCenter:coordinates radius:100 identifier:#"region3"];
[self.locationManager startMonitoringForRegion:region3 desiredAccuracy:1.0];
NSLog(#"region = %#",region3);
NSLog(#"loc max = %f",self.locationManager.maximumRegionMonitoringDistance);
NSLog(#"location manger monitored regions = %#",self.locationManager.monitoredRegions);
also implemented all delegate methods neccessary
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didfailwitherror");
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"latitude %+.10f, longitude %+.10f\n",newLocation.coordinate.latitude,newLocation.coordinate.longitude);
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
NSLog(#"didenterregion");
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region{
NSLog(#"didexitregion");
}
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{NSLog(#"monitoringDidFailForRegion");}
thanks for any help
How have you been testing the location? The regions are a little tricky, but once they are set up, they usually work great. What I usually do to test the region is just use the custom location in the Simulator. Use the same coordinates you are adding your region. 1000M is pretty large. I've tested with regions as small as 15-20M. If you have the right coordinates, it should be fine. Try switching back and forth from Apple HQ and your custom coordinates. You should be able to see the didEnter and didExit methods trip almost instantly if you have them logged out.
The one area you may have issues with is that the callbacks might not be getting to your method. None of my regions worked until I set up my AppDelegate as the CLLocationManagerDelegate. The app delegate finally got the updates and processed them correctly. I would try adding these callbacks there first, then work your way back to your mainviewcontroller. Hope this helps.
UPDATE
Since answering this question, I have learned a few things more about region monitoring. Regions get added with a minimum region size despite what you add for default. I was told by an Apple engineer that the minimum region size is 100M. I still feel they are very accurate, but it might help to understand why it will check you in. If you need precision better than 100M, you may need to look at other options.

iphone updateToLocation works differently over 3G versus wireless network?

I have a simple mapview that has the following viewdidload method and didupdate to location:
- (void)viewDidLoad {
NSLog(#"in view did load");
[super viewDidLoad];
self.mapView.showsUserLocation = YES;
self.put_url = nil;
locationManager = [[CLLocationManager alloc] init];
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager setDelegate:self];
noUpdates = 0;
[locationManager startUpdatingLocation];
self.availableParking = [[NSMutableArray alloc] init];
//self.availableParking = nil;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(#"in didupdatetolocatoin");
if([newLocation horizontalAccuracy] < 100 && [newLocation horizontalAccuracy] > 0) {
// Add annotation to map
DDAnnotation *annotation = [[DDAnnotation alloc] initWithCoordinate:newLocation.coordinate title:#"Park Here?"];
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.05;
span.longitudeDelta = 0.05;
region.span = span;
region.center = newLocation.coordinate;
self.mapView.region = region;
NSLog(#"in didupdatetolocation");
noUpdates++;
NSLog(#"IN UPDATELOCATION NOUPDATES = %d",noUpdates);
if (noUpdates == 1) {
[self.mapView addAnnotation:annotation];
NSLog(#"ADDED ANNOTATION IN didUpdateToLocation!!");
[locationManager stopUpdatingLocation];
[self.settingsViewController setState:self.mapView.userLocation.subtitle andCity:#"fuckface"];
NSLog(#"STOPPED UPDATING LOCATION");
UpdateLocation *updatedLocation = [[[UpdateLocation alloc] initWithUserid:#"fuckface" andCoordinate:newLocation.coordinate withMapViewController:self]
autorelease];
NSLog(#"Lat = %f, Long = %f",newLocation.coordinate.latitude,newLocation.coordinate.longitude);
//[NSThread detachNewThreadSelector:#selector(getLocations) toTarget:self withObject:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(sendUpdate)
name:#"NoteFromOne"
object:updatedLocation];
}
// We only update location once, and let users to do the rest of the changes by dragging annotation to place they want
} else {
NSLog(#"Accuracy not good enough %lf", [newLocation horizontalAccuracy]);
}
}
When Im connected to a wireless network it works flawlessly zooming in and dropping an annotation pin in my current location. Over the 3G network it never zooms or drops the pin. Any ideas as to why? Thanks in advance.
Here's a couple of screen shots:
With 3G:
alt text http://www.freeimagehosting.net/uploads/fe7fcbb2ea.jpg
With wifi:
alt text http://www.freeimagehosting.net/uploads/6b653e60a7.jpg
The GPS unit has nothing to do with the network connection (unless the GPS signal is not available, in which case the GPS may try to use the wifi hotspot or the cell your device is connected to in order to infer your location). It works independently of it if the GPS signal is available, and the network is only used to actually show the map. From the code snipped you posted, you only show the map when you reach an horizontal accuracy less than 100 meters, otherwise you let the GPS unit updating the location. However, if you try your code in the exact SAME place, the GPS unit on your device should always return the same updates. Therefore, I really do not understand the behaviour you are describing: this would be possible only if the GPS unit returned different updates for the same place when a different network connection is available because the GPS signal is not available. Are you seeing the same latitude/longitude in the two cases or not? Are you seeing the same accuracy? Be careful to measure this in exactly the same place in both cases.
If you obtain the same updates, then it may be possible that your 3G cellular connection is simply not powerful enough or is only apparently available, so that you did not get the map. Try testing the speed of your 3G network from the same place.
A related consideration. You should allow the GPS unit to work until either a specified amount of time elapses (say 20 seconds, use NSTimer for this) or until you reach a specified level of accuracy, whichever happens first. Otherwise you may end up consuming too much the battery.