Gps location icon is not off - iphone

In my app, I implemented Cllocation manager to use current user location & it works fine. But when the app enter in background or terminate,the GPS location icon is hide automatically in ipod. When i try same with Iphone, the icon is not hide.
So, i can't find any solution for it. Help me!!
My code is as follow:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
if(locationManager == nil)
locationManager =[[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy= kCLLocationAccuracyBest;
self.locationManager.distanceFilter= 5;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
-(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
self.userLocation=newLocation;
[self.locationManager startMonitoringSignificantLocationChanges];
}
Map.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[APPDELEGATE.locationManager startUpdatingLocation];
}
- (void)viewWillAppear:(BOOL)animated
{
self.map.delegate = self;
[self.map setShowsUserLocation:YES];
}
if i manually on location service for my app in ipod,when the app is closed, it not shown location icon. But when i try for the same in iphone,it shows location icon.

finally i solved this problem like below.
Instead of
[self.locationManager startMonitoringSignificantLocationChanges];
In appdelegate
i write,
[self.locationManager stopMonitoringSignificantLocationChanges];

I think what you really want is:
[self.locationManager stopUpdatingLocation];
directly afterward, if you want the manager to wake up on a significant location change, then call:
[self.locationManager startMonitoringSignificantLocationChanges];
The opposite applies to go back to continuous updating:
[self.locationManager stopMonitoringSignificantLocationchanges];
[self.locationManager startUpdatingLocation];
Note: When in Significant Location Change mode, the icon in status bar will still show the same as when updating location continuous. This is not an issue for concern as in the conservative mode it is still shutting the location services down when unneeded.
The ipod does not support startMonitoringSignificantLocationChanges. That is why the indicator behaves differently on the two devices.
You should consider that, as you have it implemented, you are using whatever the first event reports for location out of the manager. This can often be stale, cached, old or very likely horribly inaccurate. It is standard practice to use a bit of testing and give a chance for more suitable location info as needed for your purpose.
See my handler on Github for more help as you work with location services.

Related

GPS location is on/off in iphone for my app

i am check GPS location is on/off to use this code
BOOL servicesEnabled = [CLLocationManager locationServicesEnabled];
it work correctly when on/off LocationServices in iphone,but i am set off LocationServices for my app it return only servicesEnabled to YES,that time [CLLocationManager locationServicesEnabled] how to check locationServicesEnabled in my app
Ex: i am disable my app location services like as instagram, how to solve this problem to check LocationServices in particular app in iphone or ipad?
Use your CLLocationManagerDelegate's locationManager: didFailWithError: method and check for a kCLErrorDenied error to see if the user denied location services.
- (void)viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// Set a movement threshold for new events.
locationManager.distanceFilter = 500;
[locationManager startUpdatingLocation];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
// If it's a relatively recent event, turn off updates to save power
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"%#",error);
}
if location service disable for your app then its give you error
Error Domain=kCLErrorDomain Code=1 "The operation couldn’t be completed. (kCLErrorDomain error 1.)"

How to receive significant location changes on all application instead of only one view?

I'm new to iOS programming and I need to implement a location aware application. I can already use the significant location changes service, however when I leave my view it stops receiving new updates.
If I enter background on that view I still get the updates and everything is fine, but if I change my view to other it stops...
I think it is logical to happen this way but I need to receive updates on my other views as well...
Should I replicate the code for each view I have or can I make it that I receive the update in whatever view I am, like making my application answer instead of each view.
Thanks,
GustDD
Add this code in AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
if(!locationManager) {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
}
}
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
//here you will get upadated location
//here you can add delegate method call to where you want to use this location or you can create a shared variable
}
You could :
define the location instance in the application delegate so you can access it anytime.
use NSNotificationCenter to post a notification when the location change.
use delegates to pass info when the location changed.

Should an app start location tracking in order to get ANY last known location from CLLocationManager?

Currently, developing an app that needs to get last location from CLLocationManager (without any regular tracking). It doesn't matter how old, accurate it is. I don't need and want to start tracking - I just need to just grab some last location from a cache and that's it. IMHO, CLLocationManager is a shared component in iOS and if some app uses location tracking then another app should be able to use the most recent location from CLLocationManager.location. It should be sufficient just to alloc/init CLLocationManager and grab its location. However it's not. I have tested on iPhone4 - started google maps, saw my current location, then went to my app, but after [[CLLocationManager alloc] init] location property is nil.
UPDATE: tried [locationManager startUpdatingLocation]; and [locationManager stopUpdatingLocation]; but the result is the same. I guess, the only solution is to start regular tracking?
UPDATE2: Strange but there's no alert with "The app wants to use location services" after alloc/init of CLLocationManager. Here's my code fragment:
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
[locationManager stopUpdatingLocation];
NSLog(#"%#", locationManager.location); //prints nil
First you should check if your locationManager has a, let's say, 'static' location pre-saved.
If it does, you're done.
If not, you should startUpdatingLocation and then, in the didUpdateToLocation:fromLocation: callback, stopUpdatingLocation once you get the location.
My experience says that's the best way to get only one location.
UPDATE TO MATCH AUTHOR UPDATES:
You should not stopUpdatingLocation just after startUpdatingLocation. startUpdatingLocation starts a service in background, so you should wait until you get a location, so invoque it in the callback methods.
To make any use of CLLocationManager you need to implement CLLocationManagerDelegate somewhere.
-[CLLocationManager startUpdatingLocation] starts an async process. If you stop it in the same runloop cycle the process never gets started and that is the reason you never see the permission dialog.
It goes something like this:
#interface MyClass : NSObject <CLLocationManagerDelegate> {
CLLocationManager *manager;
CLLocation *lastLocation;
}
#end
#implementation
- (id)init {
self = [super init];
if (self) {
manager = [[CLLocationManager alloc] init];
manager.delegate = self;
[manager startUpdatingLocation];
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation;
{
lastLocation = newLocation;
[manager stopUpdatingLocation];
}
// in your real implementation be sure to handle the error cases as well.
#end

How do I get CLLLocationManager to return immediately with a location?

I am trying to tweak my CLLocationManager settings so that when I call startUpdatingLocation it calls the delegate right away. Any idea on how to do this?
Thats not possible. The reason is simple, the device has no position fix that matches your desired accuracy the whole time. It might have to turn on the GPS chip to do this which also takes some time to ge a location (without additional infos and an outdated almanac this might take up to 15 minutes in the worst case).
It's not possible to tweak CLLocationManger in that way. However, what you could do is writing a wrapper around CLLocationManager which obtains the current position on startup and returns it everytime you ask for it. However, there might be situations where the location is not (yet) available, and this approach is quite power-consuming as you are using the GPS-device all the time.
This is by far NOT the best way (not even a good way probably) to use a CLLocationManager and when I find the time I am planning on going back and changing my code to only have a single CLLocationManager within my AppDelegate and have all sub view controller call the AppDelegate for their location needs.
I have the following code in a view controller (not the main controller or app delegate either), and about 5-10 seconds after the view controller is pushed by my main views navigation controller, it starts writing to NSLog with an accurate long/lat of my position (i.e. the delegate method locationManager:didUpdateToLocation:fromLocation: starts getting called):
- (void)viewDidLoad {
[super viewDidLoad];
// ....
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager startUpdatingLocation];
// ....
}
// This will be called just a few seconds after the view appears and the
// location is accurate (if I have location services on and good sky-line of sight)
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 5.0) {
self.latitude = [NSNumber numberWithDouble:newLocation.coordinate.latitude];
self.longitude = [NSNumber numberWithDouble:newLocation.coordinate.longitude];
NSLog(#"New Latitude %+.6f, Longitude %+.6f", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
}
}
// Then, tear down the location Manager (so I can use it in another view controller)
// A bit excessive possibly, but I like to be absolutely sure that my App does not use the GPS
// when it doesn't need it to save batter life.
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[locationManager stopMonitoringSignificantLocationChanges];
[locationManager stopUpdatingHeading];
[locationManager stopUpdatingLocation];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[locationManager stopMonitoringSignificantLocationChanges];
[locationManager stopUpdatingHeading];
[locationManager stopUpdatingLocation];
}
- (void)viewDidUnload {
[locationManager stopUpdatingLocation];
[locationManager stopMonitoringSignificantLocationChanges];
[locationManager stopUpdatingHeading];
[locationManager setDelegate:nil];
self.locationManager = nil;
}
- (void)dealloc {
// ....
[locationManager stopUpdatingLocation];
[locationManager setDelegate:nil];
[locationManager release], locationManager = nil;
// ....
[super dealloc];
}
Then, in places like actionSheet:clickedButtonAtIndex:, I can get the location values on0demand with locationManager.location.coordinate.latitude / locationManager.location.coordinate.longitude or self.latitude / self.longitude.

CLLocationManager crashing on release, but why?

This might be one of those silly question where, once a solution is pointed out, makes you feel pretty stupid wondering how you didn't see it but I can't figure out why this part of my app is crashing with EXC_BAD_ACCESS (and no stack trace).
I have a CLLocationManager *locationManager (ivar declared in interface file) that gets created on viewDidLoad if locationServices is enabled:
- (void)viewDidLoad
{
[super viewDidLoad];
if ([CLLocationManager locationServicesEnabled])
[self findUserLocation];
...
}
#pragma mark - Location finder methods
- (void)findUserLocation
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
[locationManager startUpdatingLocation];
}
So the location manager starts updating location and each time and update is found, the delegate method below is called, where I check to see if I should time out or continue looking for my desiredAccuracy:
#pragma mark - CLLocationManager delegates
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if ([newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp] > 8)
[self locationManagerTimeOut];
else if ((newLocation.horizontalAccuracy <= manager.desiredAccuracy) && (newLocation.verticalAccuracy <= manager.desiredAccuracy))
[self locationManagerLockedPosition];
}
If a position is locked, this method is called:
- (void)locationManagerLockedPosition
{
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
[locationManager release], locationManager = nil;
NSLog (#"add results to view");
}
If it times out, this is the method called:
- (void)locationManagerTimeOut
{
[locationManager stopUpdatingLocation];
locationManager.delegate = nil;
[locationManager release], locationManager = nil;
NSLog (#"Time out!");
}
Problem is, in either case (time out or locked position), I get the NSLog output in the console and then 2 secs later the app crashes??
Interesting thing is, if I comment out my [locationManager release]... line, everything works fine but WHY? Also if I move the [locationManager release] to my dealloc method, no crashes either!
Am I missing something basic here?
Thanks!
Rog
I had the same issue and there's probably some problem in the depths of CLLocationManager. Fixed by doing:
[locationManager stopUpdatingLocation];
[self performSelector:#selector(discardLocationManager) onThread:[NSThread currentThread] withObject:nil waitUntilDone:NO];
and in discardLocationManager do:
- (void) discardLocationManager
{
locationManager.delegate = nil;
[locationManager release];
}
You are release the CLLocationManager instance from within a callback method, which can't be a good idea.
The CLLocationManager calls your callbacks locationManager:didUpdateToLocation:fromLocation etc. If you release the location manager instance, you're basically deallocating the object that just called you. Bad idea. That's why the app crashes.
Instead of releasing the location manager instance, you could autorelease it.
Sargon