How to detect if I am accessing iOS6-only methods? [duplicate] - ios

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a way for XCode to warn about new API calls?
I'm building an app that will support iOS 4.3 through iOS 6.x. However, I unknowingly used a method that is marked __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_6_0). This means that the selector does not exist in previous versions of iOS.
Of course, when I tested my code on an iOS 5.x device, the app crashed. I figured out what was going on, and inserted a respondsToSelector check, and default to the "iOS 4.x way" of doing things when it fails this check.
How can I prevent these bugs in the future? Is there a compile-time way to figure out that I am accessing iOS-6-only methods, so that I can add appropriate iOS feature-checks?
I don't want to accidentally ship a product that works fine on my iOS6 devices, only to have it fail on someone's iOS4.3 device, because the selector does not exist.

The answer here worked for me: https://stackoverflow.com/a/8919108/208989
Download this header: https://github.com/mattjgalloway/MJGFoundation/blob/master/Source/Utilities/MJGAvailability.h
And put the following at the top of your .pch file:
#define __IPHONE_OS_VERSION_SOFT_MAX_REQUIRED __IPHONE_4_3
#import "MJGAvailability.h"

Related

Swift warning in Xcode 14 : Method confirm(intent:) conflicts with method confirm(intent:completion:) with the same Objective-C selector

Testing the new widget for iOS 16 with Xcode 14, I'm facing an issue trying to port the iOS 14 widget with the new WidgetFamily like .accessoryInline or .accessoryRectangular.
After adding conditional macros to solve some errors in order to build for watchOS and iOS (cf Apple WWDC 22 video: https://developer.apple.com/videos/play/wwdc2022/10050/), Xcode display no red errors but yellow blocking warnings:
Method 'confirm(intent:)' with Objective-C selector
'confirmConfiguration:completion:' conflicts with method
'confirm(intent:completion:)' with the same Objective-C selector; this
is an error in Swift 6
Any idea how to solve it?
EDITED : Finally works without fix that, see answer below. But I'm still interesting to remove this warning.
Finally, it passed without fixing this warning. I remove the last errors around the extension bundle name (has to be prefixed with the watch app bundle and follow by ".xxxxxx" of your choice without any further dot). I also had a "4" (Apple Watch) value to "Targeted Device Families" in build settings (was previously "1,2" for iPhone, iPad).

DispatchQueue.main.async availability iOS 10 works on prior iOS

After migration to new swift 3we've got a lot of automatic syntax changes among which:
DispatchQueue.main.async(execute: {
// Do something
})
documentation says that it's available in iOS 10 and later.
So I expected to see unrecognized selector error when running on iOS 8 but it still works.
So I'm just wondering if it would affect some users since our deployment target is iOS 8?
I just tested it on an iPod touch running 8.4 and DispatchQueue.main.async{} works just fine.
The docs are misleading (wrong?)
I went to log a documentation problem, but wait, among lots of other stuff that's been removed from the Xcodebuilt-in documentation system, you can't log issues with the docs anymore!
I suggest filing a radar bug, then.

What happens if I use LAPolicyDeviceOwnerAuthentication on iOS 8?

In my app, I would like to know if the user has setup a passcode or fingerprint (touchID). There's a pretty easy method just for that: [LAContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:error].
However, Apple's docs say LAPolicyDeviceOwnerAuthentication is only available on iOS9 and above. I would rather not crash iOS 8 users without explanation, even if it is getting older. The thing is, I've tried it on an iOS8.4 simulator, and it seems to compile and just work.
What ill effects can happen if I use LAPolicyDeviceOwnerAuthentication on iOS 8?
I use code similar to this:
LAPolicy localAuthPolicy = LAPolicyDeviceOwnerAuthenticationWithBiometrics;
if (![[UIDevice currentDevice].systemVersion hasPrefix:#"8."]) {
localAuthPolicy = LAPolicyDeviceOwnerAuthentication;
}
This ensures I only use LAPolicyDeviceOwnerAuthentication on iOS 9 and later.
It's undocumented what actually happens on an iOS 8 device when you attempt to use LAPolicyDeviceOwnerAuthentication. It's very unlikely anything will crash but the authentication may return NO due to an unknown value or it may succeed because iOS 8 only had one valid value and it may not do any checking.
Unfortunately Objective-C doesn't provide any runtime checks for valid enum values like you can do with constants, methods, and classes.
If you use LAPolicyDeviceOwnerAuthentication on anything below iOS 9, the app will crash. That is what happened to my app when I didn't realize that this was not available on anything below iOS 9, but my app supported iOS 8.x as its minimum supported OS version.

XCode setting to see code which won't work on previous OS versions

I've written an app specifically for iOS7, and am now attempting to make it work for iOS6.
I'd really like a setting to enable warnings which highlight lines of code which won't work on iOS6. i.e. any calls to code which ONLY work on iOS7.
That way I can immediately identify any lines of code which I need to attend to before catching them during debugging.
Does this even exist?
There is two option to deal with this.
Use MJGAvailability, a drop in header file and it will make warnings if a selector is "too new".
Buy Delpoymate, it can scan your Xcode project and show you any incompatible calls.
If you use an older Xcode next to the newest, than use this snippet:
if ([self respondsToSelector:#selector(newSelector)]){
#if __IPHONE_7_0
[self newSelector];
#endif
} else {
[self oldSelector];
}
There is no way of getting a warning to appear and even if there was how would the IDE now that you would have done something to handle it like the below
if([myObject respondsToSelect:#selector(myiOS7SelectorOnly)]) {
[myObject myiOS7SelectorOnly];
}
It works the other way if you where developing an app for iOS7 and you used a deprecated method that iOS7 API doesn't use any more it would give you a warning but not the other way you will have to wait for it to turn around and crash and throw an unrecognised selector exception.
At some point I had 2 Xcode installed - Xcode 4 and Xcode 5. Xcode 4 did not have API for ios7 and it was showing all incompatibilities.
But I don't know where can you find XCode4 now and will it still show errors in ios7 code or not?
At least you can try this way.

Was I supposed to get a warning [duplicate]

This question already has an answer here:
Why is the Xcode compiler not warning me about invalid methods for my Deployment Target?
(1 answer)
Closed 9 years ago.
In my code I use
[[self presentingViewController] dismissViewControllerAnimated:YES
completion:dismissBlock];
The thing is my deployment target is set to: 5.0.
While base SDK is 6.1.
Was I not supposed to get a warning by XCode? (because I think the above method got introduced in iOS6).
Unfortunately no, Xcode doesn't check if you use symbols that are not available in your deployment SDK.
It only checks your code against the base SDK.
But you can use some third-party software for this, like DeployMate.
That being said, as others pointed it out, dismissViewControllerAnimated:completion: is available since iOS 5, so your code is safe.
But it's always a good idea to check for unavailable or deprecated APIs in your app, using something like DeployMate.
EDIT
Here's an answer to your comment:
If you deployment target is 5.0 and your base SDK 6.0, using a symbol available in the 6.0 SDK on an iOS 5 device will crash the application.
But Xcode won't warn about this when compiling, hence the need of some third-party software.
Once you identified the problematic symbol, using respondsToSelector: is the way to go, as it's better than simple version checking.
This way, you can have conditional code that will run with both SDK versions:
if( [ someObject respondsToSelector: #selector( someIOS6Method ) ] )
{ /* iOS 6 code */ }
else
{ /* iOS 5 code */ }
Only do this if you have detected SDK issues. Don't do this for everything.
According to UIVIewController class reference, this method is available from iOS 5.0 and higher.
Availability
Available in iOS 5.0 and later.
It is not ok to warn you. It doesn't have this warnining included in the default bundle of the SDK.

Resources