I have developed both iPhone & iPad application which supports for iOS 5 and iOS 6
in that application i have grabbed user current location using CLLocationManager.
when i want to stop updating receiving GPS coordinates. I have called stopUpdatingLocation
method to stop calling didUpdateToLocation method. It was woking completely fine with iOS 5 and 6 But unfortunately its not working with iOS 7.
Seems that stopUpdatingLocation method is not working .Any particular reason. ??
i had a keep a variable to monitor the life cycle of didUpdateToLocation method and stop executes it.
One thing might be possible is,
Your current location blue dot moving on your map is because you set the MKMapView's showsUserLocation to YES. It will track until you set it to NO.
Second thing,
You might be setting below thing to stop calling that method
locationManager = nil;
That does not stop monitoring, but what it does, not to refer the location manager, So now its not possible to stop monitoring.
Instead add below code & then see what happen
[locationManager stopUpdatingLocation];
locationManager=nil;
Hope it helps..
#tdevoy - Here is sample
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations lastObject];
latitude = location.coordinate.latitude;
longtitude = location.coordinate.longitude;
//stops updating current user location update
[locationManager stopUpdatingLocation];
}
Related
Have a simple app that gets gps location. I would like to get a gps location before the app initialises. It seems for me that GPS location is updated asynchronously and I do get the app screen on the background loading while the question pops up: "allow appliction to use your current location?"
Well, how can I make a callback (sorry, coming from Ruby / JS background) to wait until I get the current location.
The code:
- (void)viewWillAppear:(BOOL)animated
{
// Set the main view to utilize the entire application frame space of the device.
// Change this to suit your view's UI footprint needs in your application.
CLController = [[CoreLocationController alloc] init];
CLController.delegate = self;
[CLController.locMgr startUpdatingLocation];
self.view.frame = [[UIScreen mainScreen] applicationFrame];
[super viewWillAppear:animated];
}
in CoreLocationController.m
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSLog(#"Update location");
if([self.delegate conformsToProtocol:#protocol(CoreLocationControllerDelegate)]) {
[self.delegate locationUpdate:newLocation];
[self.locMgr stopUpdatingLocation];
# => wait initialisation until this point and than continue
You really just need to get your app up and running.
There are two things I would try (simultaneously) to handle the delay:
misdirection! Start with another screen open. Get the user interested in something else. One tap's worth of delay might be all you need to get a fix particularly if this is not a first run. On the first run when you know it will take a little time, run a little tutorial that will occupy the time.
start with the last location - this may not be right for you if inaccurate position information could be harmful but you could store the last location received when the app exits and use it as your current position when you start the app again. Of course you want to indicate that the location is a guess at best so you might want to draw your own position dot with uncertainty circle, indicating that the whole map is the uncertain area - until you get your first GPS fix and then you can begin drawing real position updates.
I think an artificial delay where you do nothing while waiting for the location to update is going to be a worse user experience than accepting that it will take a short time and trying to do as much as you can in that time.
I am using iphone simulator 4.2 and try to display or NSLog Heading and other Location services attributes e.g. Latitude, Longitude, altitude, horizontalAccuracy, VerticalAccuracy, speed. but its not showing the correct parameters and Incase of Heading its actually not firing the event.
as its execute CLLocation code
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
[self.delegate locationUpdate:newLocation];
}
and not executing CLHeading code
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
[self.delegate headingUpdate:newHeading];
}
and when I put breakpoint on these both codes it never touch CLHeading code. I am updating location and heading in init.
- (id) init{
if (self!=nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager startUpdatingLocation];
[self.locationManager startUpdatingHeading];
}
return self;
}
The problem is that I do not know that is due to simulator or there is any problem in code?
please help.
CLLocationManager needs additional hardware and hence wont work on simulator. However you can test that using the method described in this other SO question.
From the documentation:
Some location services require the presence of specific hardware on the given device. For example, heading information is available only for devices that contain a hardware compass. This class defines several methods that you can use to determine which services are currently available.
This answer can be updated for anyone using Xcode 4.2. It is still in beta status, but if you are a paid developer you will have access to it. Also, if you are a paid developer, there are some good videos from WWDC 2011 that explain how to use the simulator for location simulation.
WWDC 2011
See What's New in Core Location and Testing Your Location-Aware App Without Leaving Your Chair
**Note: Please note again that only paid developers have access to these videos
It looks like the behaviour is by default
It fires Location but not heading.
I have not tested my application in actual hard ware to confirm my though...
Anthony Desa
i have been using the significant event location manager on ios, but it seems it does not based on cell change as claimed.
i used a simple application utilising significant location event, but i could not get a repeatable, consistent or sensitive response from the ios sdk.
i plotted the route (blue line), the cell towers(place mark) and a 1000m2 grid(blue square) on the map below.
map showing route
the route was 5000m in distance.
i drove it 3 times.
test1. received 2 sig events
test2. none
test3. received 1 sig events
before u complain that my test is too small, i have been monitoring other test routes for days and all show the inconsistent shape.
i was expecting the sig event to be based on cell tower switching. so i used a jailbreak app called 'signal' to identify what is the active cell. (NB.it is surprising which cell is active. Not what i would expect.)
From monitoring the 'signal' application, the cells switched around 6-7 times from what i noticed.
yet i did not received 6-7 sig events. So i cant see any correlation between cell switching and significant events.
so i have the following questions
Q1. what is the significant event trigger?
Q2. why are the result unreliable/inconsistent.
Q3. how can i get make my app receive consistent and sensitive significant event to 500m?
This is the code that is running in the test app
-(void)initLocationManager {
if (locationManager == nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
[locationManager stopUpdatingLocation];
[locationManager startMonitoringSignificantLocationChanges];
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self initLocationManager];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(#"%#", newLocation);
[[NSNotificationCenter defaultCenter]
postNotificationName:#"PositionUpdate" object:nil];
}
-lp
Significant Location changes are determined by iOS and there is nothing you can do to change their granularity directly. Note that it's only in iOS 4 that only the cell tower locations are used. Future versions of the operating system will improve this.
But as a workaround you could switch on normal CoreLocation position updates when the app get's woken/started by a significant location change. And then once you have the perfect result, disable Location Monitoring again to allow the app to go back to hibernation.
I just did a 3 kilometer test walk in fairly-central San Francisco with my app, and got zero Significant Change location events as well. I have a toggle in my app to change to normal polling with kCLLocationAccuracyHundredMeters and got 40+ events over the same distance.
Echoing the sentiments of various other answers herein and elsewhere, I'm holding off on Significant Change until iOS 5. I think the best thing to do right now is roll-your-own business logic to poll the old Core Location way, and ratchet frequency down gradually over time (or something) to be battery friendly.
Seems like in iOS 4, Significant Change is better suited for being able to tell which end of your commute you're at than which block (or even zip code) you're on.
I'm not sure if you have already looked at this - but the WWDC 2010 session 115 (Using Core Location in iOS) might give you a better idea of the the significant location change API.
I'm not getting any location callbacks on either sim or device. I've got this code being called:
- (void)startLocationCallbacks: (NSObject*) ignore
{
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
locationManager.distanceFilter = MINIMUM_METERS;
[locationManager startUpdatingLocation];
NSLog(#"[DEBUG] [locationManager startUpdatingLocation] (%#, %#)", locationManager, locationManager.delegate);
}
and log statements at the top of both
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
and
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
but neither log statement ever gets called. Location Notifications are enabled for my app (as shown in Settings, plus I said "allow.")
What are some possible reasons that I'm not getting location updates?
Config/other info:
I have allocated locationManager, and saved it in a retain property.
I have called startUpdatingLocation
I'm using 4.1 SDK
Problem is on both Sim & iPod-touch (2nd Gen) & iPhone-3, all running 4.1
Location notifications are allowed in my app (both as indicated in Settings and because I clicked "allow" in the alert.)
I've used CLLocationManager successfully before (in many shipping apps!) This is a real hair-puller for me.
Thanks!
Whew! Ok, I found it.
It turns out that one of the ways to make a CLLocationManager not fire off location callbacks is to do all the set-up in not-the-main-thread. When I moved my setup routine to a performSelectorOnMainThread, all worked exactly as expected.
What a nightmare!
Hope this answer helps others...
Edit/clarification:
Originally, I had something like this:
- (BOOL) appDidFinishLaunchingWithOptions: (NSDictionary*) options
{
// ...[app setup, snip]
[NSThread detachNewThreadSelector: #selector(postLaunchSetupThread) toTarget: self withObject: nil];
}
- (void)postLaunchSetupThread
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
// ...[other setup, snip]
[self setupLocationManager];
[pool release];
}
- (void)setupLocationManager
{
self.myLocationManager = [[[CLLocationManager alloc] init] autorelease];
[myLocationManager startLocationUpdates];
}
But calling setupLocationManager in a thread prevented the callbacks. So my fix was to move the line
[self setupLocationManager];
out of the thread and back into appDidFinishLaunchingWithOptions
Actually you can run it from another thread as well.
From Apple documentation:
Configuration of your location manager object must always occur on a
thread with an active run loop, such as your application’s main
thread.
Just make sure your run loop is running on that thread, and the CLLocationManager events are dispatched.
More about run loop:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html
For iOS 8
1) I placed these lines right after I init'd the location manager.
if([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
2) I added NSLocationAlwaysUsageDescription to the plist and set it to a string and added a message.
3) In my target, I clicked on Capabilities tab, and then turned on Background Modes and checked "Location Updates" and "Uses Bluetooth LE accessories"
This worked for me
// check out this
//...CLLocationManager does n't call delegate method properly
//...after lot of R&D I'm using a watchdog method it calls "
https://stackoverflow.com/questions/7156920/didupdatetolocation-doesnt-gets-called-immediately/14605889#14605889
In my case it was because of my device was unable to determine location - while staying indoors GPS signal was unavailable and wi-fi was also disconnected so location manager just wasn't able to receive any location data and delegate was never called.
Once I've connected wi-fi it worked (I guess moving outdoors should also do the trick in that case, but sometimes it is not very convenient way :) )
I have a few questions about CoreLocation and GPS.
First, what method in core location is used to continually get the users current coordinates? And at what interval should these be retrieved?
Second, should these coordinates be pushed into a NSMutableArray each time they are received, so that the array of coordinates will represent the users path?
Thanks, just wanting to get started getting me mind around this.
A very abbreviated version:
First, adopt the <CLLocationManagerDelegate> protocol in your .h, and #import <CoreLocation/CoreLocation.h>.
Then in .m go:
- (void)viewDidLoad {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
CLLocationCoordinate2D here = newLocation.coordinate;
NSLog(#"%f %f ", here.latitude, here.longitude);
}
Your -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation method will get pinged every time Core Location has something to say to you, which should happen every few seconds. those CLLocation objects contain info about accuracy, so you can screen for good points in that method.
Be sure to call [locationManager stopUpdatingLocation] and then [locationManager release] at some point!
Good luck finding yourself!
The best way to is read the CLLocationManager Class Reference, which links to several example projects. The short version:
Set the delegate property to a class that will receive location updates.
Implement the CLLocationManagerDelegate protocol in the delegate.
Call the appopriate methods to start updating location and/or heading.
You are able to define what range is acceptable for accuracy as well as how often you wish to receive automatic updates (based on a distance from last point mechanism). Also you can just turn off the location manager and turn it back on at will thru some use of a timer.
As for saving the locations to build a path, its not that simple. You will continually get GPS locations at first until the desired accuracy is achieved, and for any points in the future you may get more than one that is inaccurate before you get a good location. So building a list of these points will basically just be a list of their path, along with a lot of extra points.
You could solve this by saving only those points that have the accuracy you desire, but its an imperfect world in this respect.
Best case I would suggest you keep two lists, one is the path and the other is a running list of locations where you are comparing until you get a highly accurate location, then putting that on your path list.
Some of the example projects do things along these lines, do check them out.
You will have to do the following:
If device cannot access internet
Get co-ordinates from GPS device
Send these co-ordinates via SMS
Receive and decode SMS message at the SMS gateway you have to configure to receive info from device.
Update the info on the application database or any other store you are using
Update the position on map with latest info
If device can access internet
Get co-ordinates from GPS device
Connect to application server (may be some service) and upload information
Update the info on the application database or any other store you are using
Update the position on map with latest info