When compiling my Application with Xcode 9 for IOS11 I get the following warnings:
warning: 'touchIDLockout' was deprecated in iOS 11.0: use LAErrorBiometryLockout
warning: 'touchIDNotEnrolled' was deprecated in iOS 11.0: use LAErrorBiometryNotEnrolled
warning: 'touchIDNotAvailable' was deprecated in iOS 11.0: use LAErrorBiometryNotAvailable
I'm using touchID but I'm not using touchIdLockout...cste and the touchID is working correctly.
How can I remove these warnings?
Edit (not by the original author):
I tracked this down to a single cause. It's enough to reference LAError
from the LocalAuthentication framework in my code to make these warnings appear.
Steps to reproduce (tried in Xcode 9.2):
- Create a new iOS app (Single View template). Note the iOS Deployment Target is set to iOS 11.2.
Add these lines to
AppDelegate.swift
:import LocalAuthentication
And a single line in
appDidFinishLaunching
:func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { let _: LAError? = nil return true }
Build the app.
The let _: LAError? = nil
line is enough to make the three warnings appear. The warnings are not associated with any particular line of code, though. They appear in the build log without any file/line reference:
<unknown>:0: warning: 'touchIDLockout' was deprecated in iOS 11.0: use LAErrorBiometryLockout
<unknown>:0: warning: 'touchIDNotEnrolled' was deprecated in iOS 11.0: use LAErrorBiometryNotEnrolled
<unknown>:0: warning: 'touchIDNotAvailable' was deprecated in iOS 11.0: use LAErrorBiometryNotAvailable
Here's a screenshot: Screenshot of the warnings in Xcode
And a sample project: Sample project for download (Xcode 9.2)
For reference, I reported this to Apple. Radar #36028653.
Short answer: It looks like a compiler bug to me, caused by the import of a C enumeration which defines multiple constants with the same value.
Long answer: Unfortunately I do not have a solution how to avoid the deprecation warning, only a possible explanation what causes it.
The
LAError
codes are defined as a C enumeration in<LAError.h>
in the LocalAuthentication framework. Here is an extract of that definition:One can see that "old" (deprecated) and the "new" error codes use the same values. For example, both
LAErrorTouchIDNotAvailable
andLAErrorBiometryNotAvailable
are defined as-6
.That is perfectly valid in C, but the raw values of a Swift
enum
must be mutually distinct. Apparently the Swift importer solves that by mapping the new/duplicate cases to static variables.Here is an extract of the Swift mapping:
And this seems to be the cause for the deprecation warnings, and also for the problem reported on the swift-users mailing list
that it is impossible to write an exhaustive and warning-free switch statement for
LAError
.To prove my conjecture, I have reproduced the problem with a custom enumeration: Add the following definition to the bridging header file of an macOS 10.13 or iOS 11 project:
This is imported to Swift as
with 3 cases for the first (distinct) enum values, and a static property for the duplicate value.
And indeed, any use of
MyEnum
triggers a deprecation warning:In addition, it is not possible to use the new enum value in a switch statement:
even if the compiler (apparently) knows that these cases are exhaustive:
This looks like a compiler bug to me.
As has been noted, this is a bug in the compiler. The Swift team are aware and you might want to go and vote for the bug. At the same time, add a watch on it so that you can remove the following workaround when it has been fixed.
What you need to do in order to not get the warnings is: do not mention
LAError
. Think ofLAError
as Voldemort.Instead, use Objective-C style error checking. All
Error
enums map to anNSError
, which are built up from a domain and a code. The constants to compare these with are also exported to Swift. They can be named without warnings. So your code might look a little (hopefully, very little) like this.Yes, these are new warnings which are present as Apple moves to iOS 11 and FaceID. Most likely, you are checking to see if the biometric hardware is not locked out, has enrolled fingerprints, and the device has the supporting hardware.
Here an example set up:
Up to iOS 10, one would run checks like this:
Note: iOS 11 introduced a slight variant of the above code. Instead of using
LAError.touchID
for each error property, they introducedLAError.biometry
. Therefore you would have:biometryNotAvailable
,biometryNotEnrolled
, andbiometryLockout
.Apple seems to prefer this approach, instead:
This method gets rid of Xcode's warnings.
I too struggled with this for a very long time. Oliver's answer led me to a solution that worked for me, but just in case there are others that are still having this issue - it seems that ANY reference to the old LAError values will produce the warnings listed above.
For example, this simple code produces the warnings. Remove ALL reference to the old codes and use Oliver's approach.
In fact, it can be even simpler. Try this: