You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS17下Swift LocalAuthentication中FaceID重置State变量的问题

iOS17中FaceID回调无法修改SwiftUI @State变量的问题

我尝试通过FaceID验证来修改SwiftUI里的@State布尔变量showPassword,该功能在iOS16上运行正常,但升级到iOS17后出现异常:在点击手势里先设置showPassword=true,当FaceID验证成功触发回调时,这个变量会被重置为false,即使在回调里执行showPassword=true也无法生效。

原始测试代码

import SwiftUI
import LocalAuthentication

struct PasswordEditTest: View {
    
    @State private var showPassword: Bool = false
  
    var body: some View {
        
        HStack {
            Section(header: Text("Password:").foregroundColor(Color.theme.red)
            ) {
                
                if  showPassword {
                    Text("UNLOCKED")
                }
                else {
                    Text("LOCKED")
                }
            }
            
            Spacer()
             
             Image(systemName: showPassword ? "lock.open" : "lock")
                 .resizable()
                 .scaledToFill()
                 .frame(width: 30, height: 39)
                 .padding()
                 .onTapGesture {
                     
                     let context = LAContext()
                     var error: NSError?
                    
                     if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
                         let reason = "We need to unlock your password"
                         
                         context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
                                 if success {
                                     print("SUCCESS")
                                     showPassword=true
                                 } else {
                                     print("FAIL")
                                     showPassword=false
                                 }
                         }
                     } else {
                        // 无FaceID/生物识别功能
                     }
                 }
            
        }
        
    }
    
}

出现异常的补充代码片段

.onTapGesture {
    showPassword=true // 添加此行代码
    
    let context = LAContext()
    var error: NSError?
    
    if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
        let reason = "We need to unlock your password"
        
        context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
                if success {
                    // showPassword会被重置为false
                    print("SUCCESS")
                    showPassword=true // 此行代码无法将变量设为true
                } else {
                    print("FAIL")
                    showPassword=false
                }
        }
    } else {
       // 无FaceID/生物识别功能
    }
}

解决方案

问题核心在于LAContext.evaluatePolicy的回调是在后台线程执行的,而SwiftUI的@State变量必须在主线程中修改才能正确触发视图更新。iOS17对线程检查更加严格,导致之前iOS16中可能侥幸生效的代码现在失效。

只需要将回调中修改showPassword的代码包裹在DispatchQueue.main.async中,确保在主线程执行:

context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
    DispatchQueue.main.async { // 切换到主线程更新状态
        if success {
            print("SUCCESS")
            showPassword=true
        } else {
            print("FAIL")
            showPassword=false
        }
    }
}

另外可以简化图片的frame设置,因为宽高值固定,无需根据showPassword判断:

.frame(width: 30, height: 39)

内容的提问来源于stack exchange,提问作者neogaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:55:00