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

Swift中能否在Delegate方法内使用Completion Handler?Google登录场景求助

解决方案:在单例LoginHelper中关联Google登录Delegate与Completion Handler

完全可以实现你的需求!核心思路就是在单例类里临时存储当前登录请求对应的Completion Handler,等Google登录的Delegate回调触发时,再调用这个handler并传递结果。下面是具体的实现步骤和代码示例:

1. 让LoginHelper遵循GIDSignInDelegate

首先确保你的单例类实现GIDSignInDelegate协议,这样才能接收Google登录的回调事件。

2. 临时存储Completion Handler

在单例类中添加一个可选闭包属性,用来暂存当前登录请求的completion handler。注意用完后要及时置空,避免内存泄漏或重复调用。

3. 在登录方法中配置Delegate并保存Handler

调用Google登录接口前,把当前单例设置为GIDSignIn的delegate,同时保存传入的completion handler。

4. 在Delegate方法中触发Completion Handler

当Google登录的回调方法(signIn(_:didSignInFor:withError:))被调用时,根据登录结果触发之前保存的handler,之后立即清空handler。

完整代码示例

import GoogleSignIn

class LoginHelper: NSObject, GIDSignInDelegate {
    // 单例实现
    static let shared = LoginHelper()
    private override init() { super.init() }
    
    // 暂存当前登录请求的completion handler
    private var loginCompletion: ((Bool) -> Void)?
    
    @objc func googleLoginPressed(viewController: UIViewController, isLoginSuccessfull: @escaping (Bool) -> ()) {
        // 保存传入的completion handler
        loginCompletion = isLoginSuccessfull
        
        // 配置Google登录的代理为当前单例
        GIDSignIn.sharedInstance().delegate = self
        GIDSignIn.sharedInstance().presentingViewController = viewController
        
        // 发起Google登录请求
        GIDSignIn.sharedInstance().signIn()
    }
    
    // MARK: - GIDSignInDelegate
    func signIn(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
        // 切换到主线程执行completion(Google回调可能在后台线程触发)
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            
            if let error = error {
                print("Google登录失败: \(error.localizedDescription)")
                self.loginCompletion?(false)
            } else {
                // 这里可以额外处理用户信息,比如获取token、用户昵称等
                print("Google登录成功,用户名: \(user.profile?.name ?? "未知")")
                self.loginCompletion?(true)
            }
            
            // 调用后清空handler,防止重复触发
            self.loginCompletion = nil
        }
    }
    
    // 可选:处理登出相关的回调
    func signIn(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) {
        // 这里可以添加登出后的逻辑处理
    }
}

关键注意事项

  • 内存安全:使用[weak self]避免循环引用,因为单例是全局生命周期,闭包若强引用self可能导致内存泄漏。
  • 主线程执行:Google登录的回调可能在后台线程触发,必须切换到主线程执行completion handler,确保后续UI操作(如页面跳转、提示弹窗)不会出错。
  • 清空Handler:每次调用完completion handler后务必置空loginCompletion,防止同一handler被重复调用(比如用户连续点击登录按钮的情况)。

这样就能完美实现把Google登录的Delegate回调通知到对应的Completion Handler了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:22:17