views:

296

answers:

3

locationServicesEnabled changed from a property to a method.

This is deprecated:

CLLocationManager *manager = [[CLLocationManager alloc] init];
if (manager.locationServicesEnabled == NO) {
     // ...
}

Now I should use:

if (![CLLocationManager locationServicesEnabled]) {
    // ...
}

I want to support iOS 3 and iOS 4 devices. How can I check this on iOS 3 devices and get rid of the deprecated warning?

+1  A: 

Editted:

#if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_3_1
  #if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_3_2
    if (![CLLocationManager locationServicesEnabled]) {
    // ...
    }
  #else
    CLLocationManager *manager = [[CLLocationManager alloc] init];
    if (manager.locationServicesEnabled == NO) {
       // ...
    }
  #endif
#else
CLLocationManager *manager = [[CLLocationManager alloc] init];
if (manager.locationServicesEnabled == NO) {
     // ...
}
#endif
vodkhang
Thanks. Why iOS 3.1?
testing
Ah, because when I build my app, we usually use 3.1.3, which means we can recognize the constant __IPHONE_3_1 but because 3.1.3 will be equals to 3.1 so it will go to the else branch. The reason is also 3.1.3 is the highest iphone sdk before 4.0 (3.2 is only for ipad)
vodkhang
What would be if the app would run on an iPad?
testing
What is the iPad style, likes the iphone 3.1.3 or 4.0?
vodkhang
What do you mean with iPad style? I thought iOS 3.2 is running and this would mean the else part would be executed. I don't know much about iPad development, because I'm coding for iPhone and iPod devices. But I think it is possible to install my app on an iPad. Then the else part would be executed. But this shouldn't be a problem, because deprecated doesn't mean the method isn't there. So the code would work?
testing
No, if you run the code in iPad, the if part will run and then if iOS 3.2 doesn't support that yet, your code gonna crash. So, I want to ask if iOS 3.2 supports the first or the second style
vodkhang
Hmm, iPad has iOS 3.2.2. Because (nearly) the same SDK as the iPhone is used, I think the docs are valid:>Availability>Available in iOS 2.0 and later.>Deprecated in iOS 4.0.That mean the if part will be executed and the app crashes (as you said). So it supports the second style (else part) I think.
testing
The editted code should work. Because first, in SDK 3.1, the part of testing for 3.2 will not run and it will be ok.
vodkhang
Don't I need an else part (the same as the other else part) for the inner if? Because the check for locationServicesEnabled for the iPad never takes place.
testing
You are right, you need it because if it is iPad 3.2, there is nothing run, no if is true. A little bit duplication of code but you can refactor it
vodkhang
I think I'll write a method for the else part. Thanks!
testing
A: 

Followup question: how can conditional compiling support different devices at runtime ? If I were to compile this on a 4.0 SDK, it would not run legitimately on a 3.1.3 device, because it would call the method, not the property, and that's not a supported API for 3.1.3. So wouldn't that be cause for rejection by Apple? Clearly I'm confused.

Mike
A: 

Try:

BOOL locationServicesEnabled;
CLLocationManager locationManager = [CLLocationManager new];
if( [locationManager respondsToSelector:@selector(locationServicesEnabled) ] )
{
    locationServicesEnabled = [locationManager locationServicesEnabled];
}
else
{
    locationServicesEnabled = locationManager.locationServicesEnabled;
}

As a fix/work around.

Using the compiler defines will cause you issues when using the minimum deployment target to allow older OS versions access to your application.

Chidj
I tried your approach, but `locationServicesEnabled` is always YES whether the general location services are enabled or not. I checked the other approach and he never gets in here `#if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_3_1` (tested on iPod Touch 2G with iOS 4.1) It seems that you are right with the minimum deployment target.
testing
Now I tested with the iPad, but the iPad is also hitting the method and not the property.
testing
Base SDK is 4.1 and deployment target is 3.0
testing
If `respondsToSelector` returns true I assume everything is working correct. Seems to be an error in the docs, because this should work only for iOS 4 and above.
testing
That is peculiar.We were getting crashes on our apps when they were deployed on devices where iOS < 4.0.The above solution resolved the crashes (the warnings are unlikely to disappear, but there's not really a way around that).Does the code cause a crash on your older OS devices?
Chidj
Also, as far as respondsToSelector returning true goes, both the property and the method have the same name/method signature, so that makes some sense (@synthesize will turn the .locationServicesEnabled property in to a method - locationServicesEnabled)
Chidj