[英]Biometric Authentication evaluation with swiftUI
I've been able to get a rudimentary version of Face / Touch ID working inside my app.我已经能够在我的应用程序中使用基本版本的 Face / Touch ID。 However, I want to add better fallbacks and error handling.但是,我想添加更好的回退和错误处理。
So I've been researching how to do it.所以我一直在研究怎么做。 There are fantastic resources like this:有这样很棒的资源:
Face ID evaluation process not working properly Face ID 评估过程无法正常工作
However, I can't find anything that works inside a SwiftUI view.但是,我在 SwiftUI 视图中找不到任何可用的东西。 At the moment my project won't run with:目前我的项目不会运行:
'unowned' may only be applied to class and class-bound protocol types, not 'AuthenticateView'
and和
Value of type 'AuthenticateView' has no member 'present'
any help would be much appreciated.任何帮助将非常感激。 Thank you!谢谢!
Here's my code inside AuthenticateView.swift这是我在 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)
}
Explanation:解释:
'unowned' may only be applied to class and class-bound protocol types, not 'AuthenticateView' 'unowned' 可能只适用于类和类绑定的协议类型,而不是 'AuthenticateView'
First of all, you have AuthenticateView
which is a struct
.首先,你有AuthenticateView
这是一个struct
。 You can't do it class
because whole Apple's SwiftUI idea is about structures.你不能在class
做,因为整个 Apple 的 SwiftUI 想法都是关于结构的。 And because Struct
is value type and not a Reference type, so no pointer as such.并且因为Struct
是值类型而不是引用类型,所以没有指针。 So you may not include code parts containing unowned self
and weak self
modifiers into struct AuthenticateView: View {}
因此,您可能不会将包含unowned self
和weak self
修饰符的代码部分包含到struct AuthenticateView: View {}
Value of type 'AuthenticateView' has no member 'present' 'AuthenticateView' 类型的值没有成员 'present'
present
is a UIViewController
's method. present
是一个UIViewController
的方法。 Here in SwiftUI you have no access to it.在 SwiftUI 中,您无法访问它。 The alerts are being presented using the next style:警报使用下一个样式显示:
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")))
}
}
}
Solution: For your case, I would create a class
Handler subclass of ObservableObject
for your logic and use the power of @ObservedObject
, @Published
and @State
.解决方案:对于您的情况,我将为您的逻辑创建ObservableObject
的class
Handler 子类,并使用@ObservedObject
、 @Published
和@State
。
Rough example for understanding the concept:理解概念的粗略示例:
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"
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.