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

SwiftUI:APP回到前台时在任意视图上层展示验证视图

解决SwiftUI中APP回到前台统一展示验证视图的问题

方案一:全局状态+自定义ViewModifier(纯SwiftUI方式)

通过全局状态管理验证视图的显示状态,搭配自定义ViewModifier实现全局监听,避免重复写监听代码。

  1. 全局状态管理类
import SwiftUI

class AppAuthenticationManager: ObservableObject {
    static let shared = AppAuthenticationManager()
    @Published var shouldShowAuthView = false
    
    private init() {
        // 监听进入后台,标记需要验证
        NotificationCenter.default.addObserver(self, selector: #selector(appEnteredBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
        // 监听回到前台,触发验证视图
        NotificationCenter.default.addObserver(self, selector: #selector(appEnteredForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
    }
    
    @objc private func appEnteredBackground() {
        shouldShowAuthView = true
    }
    
    @objc private func appEnteredForeground() {
        if shouldShowAuthView {
            DispatchQueue.main.async {
                self.shouldShowAuthView = true
            }
        }
    }
    
    // 验证完成后调用,重置状态
    func completeAuthentication() {
        shouldShowAuthView = false
    }
}
  1. 自定义ViewModifier
struct AuthenticationViewModifier: ViewModifier {
    @ObservedObject var authManager = AppAuthenticationManager.shared
    
    func body(content: Content) -> some View {
        content
            .fullScreenCover(isPresented: $authManager.shouldShowAuthView) {
                FullCoverViewDidEnterBg()
                    .onDisappear {
                        authManager.completeAuthentication()
                    }
            }
    }
}

// 给View扩展,方便调用
extension View {
    func addAuthenticationCover() -> some View {
        self.modifier(AuthenticationViewModifier())
    }
}
  1. 应用到视图中
@main
struct NavApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .addAuthenticationCover()
        }
    }
}

struct ContentView: View {
    @State var isPresenting = true
    var body: some View {
        NavigationStack {
            VStack {
                Button("Present Full Cover") {
                    isPresenting.toggle()
                }
                Text("Hello, world!")
            }
            .fullScreenCover(isPresented: $isPresenting) {
                FullCoverView()
                    .addAuthenticationCover() // 子全屏视图也要添加
            }
        }
    }
}

struct FullCoverView: View {
    @Environment(\.dismiss) var dismiss
    var body: some View {
        VStack {
            Text("FullCoverView")
            Button("dismiss") {
                dismiss()
            }
        }
    }
}

struct FullCoverViewDidEnterBg: View {
    @Environment(\.dismiss) var dismiss
    var body: some View {
        VStack {
            Text("请验证身份(面容ID/密码)")
            Button("验证完成") {
                dismiss()
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.white)
    }
}

方案二:借助UIKit获取顶层视图控制器(混合方式)

直接通过UIKit获取当前顶层视图控制器,强制弹出验证视图,无需修改现有SwiftUI视图结构。

  1. 扩展UIApplication获取顶层VC
import UIKit

extension UIApplication {
    func topViewController() -> UIViewController? {
        let keyWindow = connectedScenes
            .filter({$0.activationState == .foregroundActive})
            .map({$0 as? UIWindowScene})
            .compactMap({$0})
            .first?.windows
            .filter({$0.isKeyWindow}).first
        
        var topVC = keyWindow?.rootViewController
        while let presentedVC = topVC?.presentedViewController {
            topVC = presentedVC
        }
        return topVC
    }
}
  1. 修改全局状态类,用UIKit弹出视图
class AppAuthenticationManager: ObservableObject {
    static let shared = AppAuthenticationManager()
    
    private init() {
        NotificationCenter.default.addObserver(self, selector: #selector(appEnteredForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
    }
    
    @objc private func appEnteredForeground() {
        guard let topVC = UIApplication.shared.topViewController() else { return }
        
        // 将SwiftUI视图包装成UIHostingController
        let authView = FullCoverViewDidEnterBg()
        let hostingVC = UIHostingController(rootView: authView)
        hostingVC.modalPresentationStyle = .fullScreen
        
        topVC.present(hostingVC, animated: true)
    }
}
  1. 初始化管理器
@main
struct NavApp: App {
    let authManager = AppAuthenticationManager.shared
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

方案对比

  • 纯SwiftUI方案:符合SwiftUI状态驱动理念,代码易维护,但需要给每个弹出的全屏视图添加Modifier。
  • 混合UIKit方案:无需修改现有视图结构,全局强制弹出验证视图,适合已有较多页面的项目,但需要处理SwiftUI与UIKit的视图转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 08:27:52