SwiftUI:在启动/进入前台时显示“锁定屏幕”?

Sha*_*man 0 ios swiftui ipados

我正在 SwiftUI 中开发一个 iOS 应用程序,需要先锁定/解锁钥匙串中的加密密钥,然后才能执行任何操作。我希望在使用应用程序时将这些键保留在内存中,然后在用户切换到另一个应用程序或进入后台时从内存中删除。当应用程序启动或返回前台时,我想提示他们输入密码来解锁密钥。

我过去在使用 UIKit 时做过类似的事情,但这个应用程序是用 SwiftUI 编写的。我的应用程序的根目录是 a TabViewView每个选项卡中都显示许多其他 s 。我希望弹出这个“锁定屏幕”,无论View当时哪个处于活动状态。我知道我可以在UIApplicationDelegateNotification中订阅许多s 。这可以处理从内存中删除密钥的任务。我不知道如何将锁定屏幕显示在当时可能处于活动状态的任何其他屏幕之上。ViewView

是否有一种“标准”SwiftUI 方法可以实现此目的?我想尽可能遵循 SwiftUI 最佳实践,但还没有看到任何关于如何做这样的事情的好例子。

jn_*_*pdx 5

最简单的版本是使用一个if/else块根据@State变量有条件地显示锁定屏幕:

struct ContentView: View {
    @State var showLock = false
    
    var body: some View {
        Group {
            if showLock {
                Text("Locked")
            } else {
                Text("Tab view here")
            }
        }.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in
            showLock = true
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

上述方法的缺点是,当显示锁定屏幕时,您可能会丢失选项卡视图中的某些状态。

要保持选项卡视图加载并保持状态,您可以使用fullScreenCover显示在其他内容之上的 :

struct ContentView: View {
    @State var showLock = false
    
    var body: some View {
        Text("Tab view here")
        .fullScreenCover(isPresented: $showLock) {
            VStack {
                Text("Locked")
                Button("Hide") {
                    showLock = false
                }
            }
        }
        .onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in
            showLock = true
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,存储状态(锁定/解锁)的位置无关紧要——您可以将其存储在ObservableObject环境密钥等中——任何 SwiftUI 可以看到它更新的地方。获取后台/前台通知的策略也是如此——任何设置状态的策略都是可行的。