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

如何从ASWebAuthenticationSession回调回到SwiftUI视图?

实现ASWebAuthenticationSession结果回传至SwiftUI视图

要完成从ASWebAuthenticationSession的completion handler携带认证code返回SwiftUI视图并处理,核心是利用ObservableObject的响应式属性传递状态,具体步骤如下:

1. 改造AuthSession类,添加响应式状态

因为AuthSession已经实现了ObservableObject,可以通过@Published属性将认证结果暴露给SwiftUI视图:

class AuthSession: NSObject, ObservableObject, ASWebAuthenticationPresentationContextProviding {
    // 用于存储认证code
    @Published var authCode: String?
    // 标记认证是否成功
    @Published var isAuthenticated = false
    // 存储认证错误信息
    @Published var authError: Error?
    
    private(set) var webAuthSession: ASWebAuthenticationSession!

    override init() {
        super.init()
        webAuthSession = ASWebAuthenticationSession(
            url: AuthHandler.shared.signInURL()!,
            callbackURLScheme: "your-scheme", // 替换为实际的回调scheme
            completionHandler: { [weak self] callbackURL, error in
                guard let self = self else { return }
                
                if let error = error {
                    self.authError = error
                    self.isAuthenticated = false
                    return
                }
                
                // 从回调URL中解析认证code
                if let callbackURL = callbackURL,
                   let components = URLComponents(url: callbackURL, resolvingAgainstBaseURL: false),
                   let codeItem = components.queryItems?.first(where: { $0.name == "code" }),
                   let code = codeItem.value {
                    
                    self.authCode = code
                    self.isAuthenticated = true
                } else {
                    self.isAuthenticated = false
                    self.authError = NSError(domain: "AuthError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无法获取认证code"])
                }
            }
        )
        webAuthSession.presentationContextProvider = self
        webAuthSession.prefersEphemeralWebBrowserSession = true
    }

    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        // 返回当前的主窗口,确保弹窗正确显示
        return UIApplication.shared.windows.first(where: { $0.isKeyWindow }) ?? ASPresentationAnchor()
    }
}

2. 调整SignInView,正确持有AuthSession并监听状态

SwiftUI视图需要持有AuthSession实例,并通过监听@Published属性的变化来触发后续逻辑:

struct SignInView: View {
    @EnvironmentObject var signedIn: UIState
    // 使用@StateObject持有AuthSession实例,确保生命周期与视图一致
    @StateObject private var authSession = AuthSession()
    
    var body: some View {
        Button("开始认证") {
            authSession.webAuthSession.start()
        }
        // 监听认证状态变化
        .onReceive(authSession.$isAuthenticated) { isAuthenticated in
            guard isAuthenticated else {
                // 处理认证失败逻辑,比如展示错误
                if let error = authSession.authError {
                    print("认证失败: \(error.localizedDescription)")
                }
                return
            }
            
            // 认证成功,拿到code执行后续处理
            if let code = authSession.authCode {
                signedIn.isSignedIn = true
                // 这里可以调用API交换token等逻辑
                print("获取到认证code: \(code)")
            }
        }
    }
}

关键说明

  • @StateObject:确保AuthSession实例在视图生命周期内唯一,避免重复创建会话
  • @Published属性:当completion handler中更新这些属性时,SwiftUI会自动刷新视图并触发后续逻辑
  • 回调URL解析:要确保callbackURLScheme与认证服务配置的一致,才能正确获取到包含code的回调URL
  • 弱引用[weak self]:避免completion handler持有AuthSession导致的循环引用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 01:25:31