iOS SwiftUI中收到openURL后如何自动关闭SFSafariViewController
实现方案
核心思路是将控制SFSafariViewController显隐的状态变量改为可全局访问,收到openURL回调时修改状态即可自动关闭弹窗,以下是两种可直接落地的实现方式:
方案1:全局状态管理(更适合中大型项目)
- 新增全局状态管理类
import SwiftUI class AppState: ObservableObject { // 专门控制登录流程Safari弹窗的显隐 @Published var isShowingLoginSafari = false }
- 修改App入口,注入全局状态并处理回调
@main struct MyApplication: App { @StateObject private var appState = AppState() var body: some Scene { WindowGroup { ContentView() .environmentObject(appState) .onOpenURL { url in // 先校验回调URL的合法性,比如匹配你的App自定义scheme guard url.scheme == "你配置的App回调scheme" else { return } // 直接修改全局状态关闭弹窗 appState.isShowingLoginSafari = false // 后续解析登录参数、处理登录状态的逻辑可写在这里 } } } }
- 替换原页面的状态绑定
struct Myview: View { @EnvironmentObject var appConfiguration : AppConfiguration // 引入全局状态 @EnvironmentObject var appState: AppState @State private var isLoginActive = true var body: some View { NavigationView { Button("登录") { // 点击时修改全局状态打开Safari appState.isShowingLoginSafari = true } } .afklPageView() .navigationBarTitle("title", displayMode: .inline) // 绑定全局状态控制弹窗 .fullScreenCover(isPresented: $appState.isShowingLoginSafari, content: { if let url = loginAction() { SafariView(url: url) } }) } }
方案2:通知中心实现(更适合小型项目)
不需要修改全局架构,直接通过通知跨页面传递关闭事件:
- 在
openURL回调中发送关闭通知
@main struct MyApplication: App { var body: some Scene { WindowGroup { ContentView() .onOpenURL { url in guard url.scheme == "你配置的App回调scheme" else { return } NotificationCenter.default.post( name: NSNotification.Name("DismissLoginSafari"), object: nil ) } } } }
- 在原页面监听通知修改状态
struct Myview: View { @EnvironmentObject var appConfiguration : AppConfiguration @State private var isButtonActive = true @State private var isLoginActive = true var body: some View { NavigationView { Button("登录") { self.isButtonActive = true } } .afklPageView() .navigationBarTitle("title", displayMode: .inline) .fullScreenCover(isPresented: $isButtonActive, content: { if let url = loginAction() { SafariView(url: url) } }) // 监听关闭通知 .onAppear { NotificationCenter.default.addObserver( forName: NSNotification.Name("DismissLoginSafari"), object: nil, queue: .main ) { _ in isButtonActive = false } } } }
注意事项
需要提前在项目Info.plist中配置你自定义的URL Scheme,否则App无法收到对应的openURL回调。
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

