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
相关产品推荐
相关产品推荐

