无法检测WKWebView中Sign in with Apple弹窗Cancel按钮点击事件的问题
解决方案
你之前注入JS监听事件的方案无法生效,核心原因是你看到的登录弹窗是系统级弹窗,不属于WKWebView加载页面的DOM元素,且你直接加载授权URL的场景下页面不会抛出你监听的AppleIDSignInOnFailure事件。以下是两种可行的实现方案:
方案一:使用官方推荐的ASWebAuthenticationSession(优先选择)
苹果官方明确要求Sign in with Apple的网页授权场景使用ASWebAuthenticationSession处理,该类自带完成回调,可直接获取用户取消、授权成功等状态,无需自行维护WKWebView:
import AuthenticationServices // 初始化授权请求 let authURL = URL(string: "https://appleid.apple.com/auth/authorize?response_type=code&client_id=...&redirect_uri=...&response_mode=...")! let session = ASWebAuthenticationSession(url: authURL, callbackURLScheme: "你的redirect_uri的scheme") { callbackURL, error in // 用户点击Cancel会直接走error回调 if let error = error as? ASWebAuthenticationSessionError, error.code == .canceledLogin { // 此处执行关闭VC的逻辑 self.dismiss(animated: true) return } // 授权成功的后续逻辑处理callbackURL } session.presentationContextProvider = self session.start()
需要对应让你的VC遵守ASWebAuthenticationPresentationContextProviding协议:
extension YourViewController: ASWebAuthenticationPresentationContextProviding { func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor { return self.view.window! } }
方案二:若必须自行使用WKWebView加载,拦截重定向请求
用户点击Cancel按钮后,苹果授权服务会重定向到你传入的redirect_uri,并携带error=user_cancelled的查询参数,你可以通过WKNavigationDelegate的代理方法拦截该请求判断取消状态:
- 给WKWebView设置navigationDelegate
webView.navigationDelegate = self
- 实现代理方法拦截重定向
extension YourViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let url = navigationAction.request.url, url.absoluteString.hasPrefix("你填的redirect_uri") else { decisionHandler(.allow) return } // 解析URL查询参数判断是否为用户取消 if let components = URLComponents(url: url, resolvingAgainstBaseURL: false), let error = components.queryItems?.first(where: { $0.name == "error" })?.value, error == "user_cancelled" { // 执行关闭VC逻辑 dismiss(animated: true) decisionHandler(.cancel) return } // 其他状态(比如授权成功)的处理逻辑 decisionHandler(.allow) } }
- 若你的授权参数
response_mode设置为form_post,取消的错误参数会放在请求体中,可通过navigationAction.request.httpBody解析参数判断。
内容的提问来源于stack exchange,提问作者AnnaV
相关产品推荐
相关产品推荐

