使用 swiftUI 进行生物认证评估
Biometric Authentication evaluation with swiftUI
我已经能够在我的应用程序中使用 Face/Touch ID 的基本版本。但是,我想添加更好的回退和错误处理。
所以我一直在研究如何去做。有这样很棒的资源:
但是,我找不到任何在 SwiftUI 视图中工作的东西。目前我的项目不会 运行 与:
'unowned' may only be applied to class and class-bound protocol types, not 'AuthenticateView'
和
Value of type 'AuthenticateView' has no member 'present'
如有任何帮助,我们将不胜感激。谢谢!
这是我的代码 AuthenticateView.swift
func Authenticate(completion: @escaping ((Bool) -> ())){
//Create a context
let authenticationContext = LAContext()
var error:NSError?
//Check if device have Biometric sensor
let isValidSensor : Bool = authenticationContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
if isValidSensor {
//Device have BiometricSensor
//It Supports TouchID
authenticationContext.evaluatePolicy(
.deviceOwnerAuthenticationWithBiometrics,
localizedReason: "Touch / Face ID authentication",
reply: { [unowned self] (success, error) -> Void in
if(success) {
// Touch / Face ID recognized success here
completion(true)
} else {
//If not recognized then
if let error = error {
let strMessage = self.errorMessage(errorCode: error._code)
if strMessage != ""{
self.showAlertWithTitle(title: "Error", message: strMessage)
}
}
completion(false)
}
})
} else {
let strMessage = self.errorMessage(errorCode: (error?._code)!)
if strMessage != ""{
self.showAlertWithTitle(title: "Error", message: strMessage)
}
}
}
func errorMessage(errorCode:Int) -> String{
var strMessage = ""
switch errorCode {
case LAError.Code.authenticationFailed.rawValue:
strMessage = "Authentication Failed"
case LAError.Code.userCancel.rawValue:
strMessage = "User Cancel"
case LAError.Code.systemCancel.rawValue:
strMessage = "System Cancel"
case LAError.Code.passcodeNotSet.rawValue:
strMessage = "Please goto the Settings & Turn On Passcode"
case LAError.Code.touchIDNotAvailable.rawValue:
strMessage = "TouchI or FaceID DNot Available"
case LAError.Code.touchIDNotEnrolled.rawValue:
strMessage = "TouchID or FaceID Not Enrolled"
case LAError.Code.touchIDLockout.rawValue:
strMessage = "TouchID or FaceID Lockout Please goto the Settings & Turn On Passcode"
case LAError.Code.appCancel.rawValue:
strMessage = "App Cancel"
case LAError.Code.invalidContext.rawValue:
strMessage = "Invalid Context"
default:
strMessage = ""
}
return strMessage
}
func showAlertWithTitle( title:String, message:String ) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let actionOk = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(actionOk)
self.present(alert, animated: true, completion: nil)
}
解释:
'unowned' may only be applied to class and class-bound protocol types, not 'AuthenticateView'
首先,你有 AuthenticateView
,这是一个 struct
。你不能这样做 class
因为整个 Apple 的 SwiftUI 想法 is about structures. 而且因为 Struct
是值类型而不是引用类型,所以没有这样的指针。因此,您可能不会将包含 unowned self
和 weak self
修饰符的代码部分包含到 struct AuthenticateView: View {}
中
Value of type 'AuthenticateView' has no member 'present'
present
是 UIViewController
的方法。在 SwiftUI 中,您无权访问它。正在使用下一种样式显示警报:
struct ContentView: View {
@State private var show = false
var body: some View {
Button(action: { self.show = true }) { Text("Click") }
.alert(isPresented: $showingAlert) {
Alert(title: Text("Title"),
message: Text("Message"),
dismissButton: .default(Text("Close")))
}
}
}
解决方法:
对于您的情况,我会为您的逻辑创建一个 ObservableObject
的 class
处理程序子类,并使用 @ObservedObject
、@Published
和 @State
.[=29 的强大功能=]
理解概念的粗略示例:
import SwiftUI
struct ContentView: View {
@ObservedObject var handler = Handler()
var body: some View {
Button(action: { self.handler.toggleShowAlert() }) { Text("Click") }
.alert(isPresented: $handler.shouldShowAlert) {
Alert(title: Text(handler.someTitle),
message: Text(handler.someMessage),
dismissButton: .default(Text("Close")))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
class Handler: ObservableObject {
@Published var shouldShowAlert: Bool = false
@Published var someTitle = ""
@Published var someMessage = ""
func toggleShowAlert() {
shouldShowAlert.toggle()
someTitle = "ErrorTitle"
someMessage = "ErrorMessage"
}
}
我已经能够在我的应用程序中使用 Face/Touch ID 的基本版本。但是,我想添加更好的回退和错误处理。
所以我一直在研究如何去做。有这样很棒的资源:
但是,我找不到任何在 SwiftUI 视图中工作的东西。目前我的项目不会 运行 与:
'unowned' may only be applied to class and class-bound protocol types, not 'AuthenticateView'
和
Value of type 'AuthenticateView' has no member 'present'
如有任何帮助,我们将不胜感激。谢谢!
这是我的代码 AuthenticateView.swift
func Authenticate(completion: @escaping ((Bool) -> ())){
//Create a context
let authenticationContext = LAContext()
var error:NSError?
//Check if device have Biometric sensor
let isValidSensor : Bool = authenticationContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
if isValidSensor {
//Device have BiometricSensor
//It Supports TouchID
authenticationContext.evaluatePolicy(
.deviceOwnerAuthenticationWithBiometrics,
localizedReason: "Touch / Face ID authentication",
reply: { [unowned self] (success, error) -> Void in
if(success) {
// Touch / Face ID recognized success here
completion(true)
} else {
//If not recognized then
if let error = error {
let strMessage = self.errorMessage(errorCode: error._code)
if strMessage != ""{
self.showAlertWithTitle(title: "Error", message: strMessage)
}
}
completion(false)
}
})
} else {
let strMessage = self.errorMessage(errorCode: (error?._code)!)
if strMessage != ""{
self.showAlertWithTitle(title: "Error", message: strMessage)
}
}
}
func errorMessage(errorCode:Int) -> String{
var strMessage = ""
switch errorCode {
case LAError.Code.authenticationFailed.rawValue:
strMessage = "Authentication Failed"
case LAError.Code.userCancel.rawValue:
strMessage = "User Cancel"
case LAError.Code.systemCancel.rawValue:
strMessage = "System Cancel"
case LAError.Code.passcodeNotSet.rawValue:
strMessage = "Please goto the Settings & Turn On Passcode"
case LAError.Code.touchIDNotAvailable.rawValue:
strMessage = "TouchI or FaceID DNot Available"
case LAError.Code.touchIDNotEnrolled.rawValue:
strMessage = "TouchID or FaceID Not Enrolled"
case LAError.Code.touchIDLockout.rawValue:
strMessage = "TouchID or FaceID Lockout Please goto the Settings & Turn On Passcode"
case LAError.Code.appCancel.rawValue:
strMessage = "App Cancel"
case LAError.Code.invalidContext.rawValue:
strMessage = "Invalid Context"
default:
strMessage = ""
}
return strMessage
}
func showAlertWithTitle( title:String, message:String ) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let actionOk = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(actionOk)
self.present(alert, animated: true, completion: nil)
}
解释:
'unowned' may only be applied to class and class-bound protocol types, not 'AuthenticateView'
首先,你有 AuthenticateView
,这是一个 struct
。你不能这样做 class
因为整个 Apple 的 SwiftUI 想法 is about structures. 而且因为 Struct
是值类型而不是引用类型,所以没有这样的指针。因此,您可能不会将包含 unowned self
和 weak self
修饰符的代码部分包含到 struct AuthenticateView: View {}
Value of type 'AuthenticateView' has no member 'present'
present
是 UIViewController
的方法。在 SwiftUI 中,您无权访问它。正在使用下一种样式显示警报:
struct ContentView: View {
@State private var show = false
var body: some View {
Button(action: { self.show = true }) { Text("Click") }
.alert(isPresented: $showingAlert) {
Alert(title: Text("Title"),
message: Text("Message"),
dismissButton: .default(Text("Close")))
}
}
}
解决方法:
对于您的情况,我会为您的逻辑创建一个 ObservableObject
的 class
处理程序子类,并使用 @ObservedObject
、@Published
和 @State
.[=29 的强大功能=]
理解概念的粗略示例:
import SwiftUI
struct ContentView: View {
@ObservedObject var handler = Handler()
var body: some View {
Button(action: { self.handler.toggleShowAlert() }) { Text("Click") }
.alert(isPresented: $handler.shouldShowAlert) {
Alert(title: Text(handler.someTitle),
message: Text(handler.someMessage),
dismissButton: .default(Text("Close")))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
class Handler: ObservableObject {
@Published var shouldShowAlert: Bool = false
@Published var someTitle = ""
@Published var someMessage = ""
func toggleShowAlert() {
shouldShowAlert.toggle()
someTitle = "ErrorTitle"
someMessage = "ErrorMessage"
}
}