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

Swift中Firebase自定义reCAPTCHA的FIRAuthUIDelegate使用疑问

解决自定义SFSafariViewController展示Firebase reCAPTCHA的问题

我完全懂你遇到的困惑——Firebase文档只说了要实现FIRAuthUIDelegate,但没给具体的视图控制器创建和使用示例,这就很头疼。别担心,我给你一步步拆解,附上完整的代码示例:


1. 先搞懂核心逻辑

Firebase调用verifyPhoneNumber:UIDelegate:completion:时,会通过FIRAuthUIDelegate的方法通知你展示验证页面。默认它会传一个系统的SFSafariViewController,我们的目标就是拦截这个过程,替换成自己配置的自定义版SFSafariViewController。

2. 实现自定义的FIRAuthUIDelegate类

这个类既要遵守协议,又要负责创建和展示我们的自定义浏览器控制器:

import UIKit
import FirebaseAuth
import SafariServices

class CustomAuthUIDelegate: NSObject, FIRAuthUIDelegate {
    // 持有用来present页面的父控制器
    private let presentingVC: UIViewController
    
    init(presentingVC: UIViewController) {
        self.presentingVC = presentingVC
        super.init()
    }
    
    // 协议必填方法:处理验证页面的展示
    func authUI(_ authUI: FIRAuthUI, present viewController: UIViewController) {
        // 先从Firebase提供的控制器里拿到reCAPTCHA的URL
        guard let defaultSafariVC = viewController as? SFSafariViewController,
              let recaptchaURL = defaultSafariVC.url else {
            // 兜底:如果拿不到URL,就用默认方式展示
            presentingVC.present(viewController, animated: true)
            return
        }
        
        // 创建自定义的SFSafariViewController
        let customSafariVC = SFSafariViewController(url: recaptchaURL)
        
        // 这里就是你自定义的空间啦,比如修改导航栏样式
        customSafariVC.preferredBarTintColor = .systemIndigo
        customSafariVC.preferredControlTintColor = .white
        // 还可以设置其他配置,比如是否允许折叠导航栏
        customSafariVC.configuration.barCollapsingEnabled = false
        
        // 设置代理监听页面关闭事件
        customSafariVC.delegate = self
        
        // 展示我们的自定义控制器
        presentingVC.present(customSafariVC, animated: true)
    }
    
    // 协议必填方法:处理验证页面的关闭
    func authUI(_ authUI: FIRAuthUI, dismiss viewController: UIViewController) {
        presentingVC.dismiss(animated: true)
    }
}

// 扩展实现SFSafariViewControllerDelegate,处理自定义关闭逻辑
extension CustomAuthUIDelegate: SFSafariViewControllerDelegate {
    func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
        // 页面关闭时可以做一些清理操作,比如通知验证流程取消
        controller.dismiss(animated: true)
    }
}

3. 在业务代码中使用自定义Delegate

比如在你的登录页面ViewController里,调用Firebase的手机号验证时传入这个Delegate:

import UIKit
import FirebaseAuth

class LoginViewController: UIViewController {
    
    @IBAction func sendVerificationCodeTapped(_ sender: UIButton) {
        let phoneNumber = "+86138xxxxxxx" // 替换成用户输入的手机号
        // 初始化自定义Delegate,传入当前控制器作为present的父VC
        let customUIDelegate = CustomAuthUIDelegate(presentingVC: self)
        
        // 调用Firebase的手机号验证方法,传入自定义Delegate
        PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: customUIDelegate) { verificationID, error in
            if let error = error {
                print("验证请求出错:\(error.localizedDescription)")
                return
            }
            // 保存verificationID,后续用来验证用户输入的验证码
            UserDefaults.standard.set(verificationID, forKey: "AuthVerificationID")
        }
    }
}

关键注意点

  • 一定要确保能从Firebase提供的viewController中解析出reCAPTCHA的URL,目前Firebase用的是SFSafariViewController,所以这个解析是安全的;如果后续Firebase更换了VC类型,可能需要调整解析逻辑。
  • 你可以根据需求自由定制SFSafariViewController的样式和行为,比如添加自定义导航按钮、调整动画效果等。
  • 别忘了实现SFSafariViewControllerDelegate,处理页面关闭后的逻辑,避免内存泄漏或流程异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:22:35