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

iOS SwiftUI中收到openURL后如何自动关闭SFSafariViewController

实现方案

核心思路是将控制SFSafariViewController显隐的状态变量改为可全局访问,收到openURL回调时修改状态即可自动关闭弹窗,以下是两种可直接落地的实现方式:


方案1:全局状态管理(更适合中大型项目)

  1. 新增全局状态管理类
import SwiftUI
class AppState: ObservableObject {
    // 专门控制登录流程Safari弹窗的显隐
    @Published var isShowingLoginSafari = false
}
  1. 修改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
                    // 后续解析登录参数、处理登录状态的逻辑可写在这里
                }
        }
    }
}
  1. 替换原页面的状态绑定
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:通知中心实现(更适合小型项目)

不需要修改全局架构,直接通过通知跨页面传递关闭事件:

  1. 在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
            )
        }
    }
  }
}
  1. 在原页面监听通知修改状态
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 09:09:03