ios - touchIDLockout 在 iOS 11.0 中被弃用

标签 ios swift xcode compilation touch-id

在为 IOS11 使用 Xcode 9 编译我的应用程序时,我收到以下警告:

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

我正在使用 touchID 但我没有使用 touchIdLockout...cste 并且 touchID 工作正常。

如何删除这些警告?


编辑(非原作者):

我将此归结为一个原因。在我的代码中从 LocalAuthentication 框架引用 LAError 就足以使这些警告出现。

重现步骤(在 Xcode 9.2 中试过):

  1. 创建一个新的 iOS 应用(单 View 模板)。请注意,iOS 部署目标设置为 iOS 11.2。
  2. 将这些行添加到 AppDelegate.swift:

    import LocalAuthentication
    

    appDidFinishLaunching 中的一行:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        let _: LAError? = nil
        return true
    }
    
  3. 构建应用。

let _: LAError? = nil 行足以使三个警告出现。不过,这些警告与任何特定代码行无关。它们出现在没有任何文件/行引用的构建日志中:

<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

这是一个截图: Screenshot of the warnings in Xcode

和示例项目: Sample project for download (Xcode 9.2)

作为引用,我已将此事报告给 Apple。雷达#36028653。

最佳答案

简短回答:对我来说这看起来像是一个编译器错误,导致 通过导入定义多个常量的 C 枚举 具有相同的值。

长答案:不幸的是,我没有如何避免弃用的解决方案 警告,只是可能的解释是什么原因造成的。

LAError代码被定义为 C 枚举 <LAError.h>在 LocalAuthentication 框架中。这是一个 该定义的摘录:

// Error codes
#define kLAErrorAuthenticationFailed                       -1
#define kLAErrorUserCancel                                 -2
// ...
#define kLAErrorTouchIDNotAvailable                        -6
#define kLAErrorTouchIDNotEnrolled                         -7
#define kLAErrorTouchIDLockout                             -8
// ...
#define kLAErrorBiometryNotAvailable                        kLAErrorTouchIDNotAvailable
#define kLAErrorBiometryNotEnrolled                         kLAErrorTouchIDNotEnrolled
#define kLAErrorBiometryLockout                             kLAErrorTouchIDLockout

typedef NS_ENUM(NSInteger, LAError)
{
    LAErrorAuthenticationFailed = kLAErrorAuthenticationFailed,
    LAErrorUserCancel = kLAErrorUserCancel,
    // ...
    LAErrorTouchIDNotAvailable NS_ENUM_DEPRECATED(10_10, 10_13, 8_0, 11_0, "use LAErrorBiometryNotAvailable") = kLAErrorTouchIDNotAvailable,
    LAErrorTouchIDNotEnrolled NS_ENUM_DEPRECATED(10_10, 10_13, 8_0, 11_0, "use LAErrorBiometryNotEnrolled") = kLAErrorTouchIDNotEnrolled,
    LAErrorTouchIDLockout NS_ENUM_DEPRECATED(10_11, 10_13, 9_0, 11_0, "use LAErrorBiometryLockout")
    __WATCHOS_DEPRECATED(3.0, 4.0, "use LAErrorBiometryLockout") __TVOS_DEPRECATED(10.0, 11.0, "use LAErrorBiometryLockout") = kLAErrorTouchIDLockout,
    // ...
    LAErrorBiometryNotAvailable NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryNotAvailable,
    LAErrorBiometryNotEnrolled NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryNotEnrolled,
    LAErrorBiometryLockout NS_ENUM_AVAILABLE(10_13, 11_0) __WATCHOS_AVAILABLE(4.0) __TVOS_AVAILABLE(11.0) = kLAErrorBiometryLockout,
    // ...
} NS_ENUM_AVAILABLE(10_10, 8_0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0);

可以看到“旧”(已弃用)和"new"错误代码使用 相同的值。例如,LAErrorTouchIDNotAvailableLAErrorBiometryNotAvailable定义为 -6 .

这在 C 中完全有效,但 Swift 的原始值 enum必须 互不相同。显然 Swift 进口商解决了这个问题 将新的/重复的案例映射到静态变量。

这是 Swift 映射的摘录:

public struct LAError {

    public init(_nsError: NSError)
    public static var _nsErrorDomain: String { get }


    public enum Code : Int {
        case authenticationFailed
        case userCancel
        // ...
        @available(iOS, introduced: 8.0, deprecated: 11.0, message: "use LAErrorBiometryNotAvailable")
        case touchIDNotAvailable
        @available(iOS, introduced: 8.0, deprecated: 11.0, message: "use LAErrorBiometryNotEnrolled")
        case touchIDNotEnrolled
        @available(iOS, introduced: 9.0, deprecated: 11.0, message: "use LAErrorBiometryLockout")
        case touchIDLockout
        // ...
        @available(iOS 11.0, *)
        public static var biometryNotAvailable: LAError.Code { get }
        @available(iOS 11.0, *)
        public static var biometryNotEnrolled: LAError.Code { get }
        @available(iOS 11.0, *)
        public static var biometryLockout: LAError.Code { get }
        // ...
    }

    // ...
}

这似乎是弃用警告的原因,并且 也针对 swift-users 邮件列表中报告的问题

不可能写出详尽无警告的 LAError 的 switch 语句.


为了证明我的猜想,我用一个习惯重现了这个问题 枚举:将以下定义添加到桥接 header macOS 10.13 或 iOS 11 项目的文件:

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, MyEnum)
{
    MyEnumA = 1,
    MyEnumB = 2,
    MyEnumC NS_ENUM_DEPRECATED(10_10, 10_13, 8_0, 11_0, "use MyEnumNewC") = 3,

    MyEnumNewC NS_ENUM_AVAILABLE(10_13, 11_0) = 3,
};

这是导入到 Swift 中的

 public enum MyEnum : Int {
    case A
    case B
    @available(OSX, introduced: 10_10, deprecated: 10_13, message: "use MyEnumNewC")
    case C

    @available(OSX 10_13, *)
    public static var newC: MyEnum { get }
 }

第一个(不同的)枚举值有 3 个案例,还有一个静态的 重复值的属性。

事实上,任何对 MyEnum 的使用触发弃用警告:

// main.swift:
print(MyEnum.A) // Or: let _: MyEnum? = nil

// Build log:
// <unknown>:0: warning: 'C' was deprecated in OS X 10.13: use MyEnumNewC

此外,不可能在a中使用新的枚举值 切换语句:

func foo(err: MyEnum) {
    switch err {
    case .A:
        print("A")
    case .B:
        print("B")
    case .newC:
        print("C")
    }
}

// Build log:
// main.swift:12:9: error: switch must be exhaustive
// <unknown>:0: warning: 'C' was deprecated in OS X 10.13: use MyEnumNewC

即使编译器(显然)知道这些情况是详尽无遗的:

func foo(err: MyEnum) {
    switch err { // Switch must be exhaustive
    case .A:
        print("A")
    case .B:
        print("B")
    case .newC:
        print("C")
    default:
        print("default")
    }
}

// Build log:
// <unknown>:0: warning: 'C' was deprecated in OS X 10.13: use MyEnumNewC
// main.swift:19:9: warning: default will never be executed

对我来说这看起来像是一个编译器错误。

关于ios - touchIDLockout 在 iOS 11.0 中被弃用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46455424/

相关文章:

iphone - 在不重启设备的情况下禁用主页按钮

ios - 没有这样的模块 'OneSignal'

ios - Apple 对 Paypal 交易收费吗?

swift - 无法将 UIImage 放入 UIScrollview 中

ios - 使用 Swift 4.0 编译的模块无法在 Swift 4.0.1 中导入

ios - 如何从终端配置代码签名身份

iphone - UITableViewCell 选择器 setSelected :animated: gets called many times?

ios - 跑卫登录

swift - 避免在 Swift 中的排序闭包内强制展开

iOS Today Extension - 共享核心数据