iOS应用Google Sign In流程中断报错(Code-4/-5)求助
iOS Google Sign In 流程中断(错误码-4/-5)排查与修复
问题描述
开发iOS应用集成Google Sign In,编译正常,但点击登录按钮后,授权弹窗几秒后自动消失,报错:
This is the error: Optional("The operation couldn’t be completed. (com.google.GIDSignIn error -4.)")
error with signing in: Optional(Error Domain=com.google.GIDSignIn Code=-5 "The user canceled the sign-in flow." UserInfo={NSLocalizedDescription=The user canceled the sign-in flow.})
错误码解析
- Error -4: 钥匙链访问错误,通常是应用没有正确的钥匙链权限,或者Client ID配置不匹配
- Error -5: 表面显示用户取消,但实际是登录流程因底层错误(如-4)被强制终止,并非用户主动操作
解决方案
1. 检查Google Cloud控制台配置
- 确认使用的是iOS类型的Client ID,而非Web或Android类型
- 验证控制台中填写的
Bundle ID与Xcode项目的Bundle Identifier完全一致(大小写敏感) - 确保已在控制台启用Google Sign In API
- 检查Redirect URI格式是否正确:
com.googleusercontent.apps.{你的Client ID}:/oauth2redirect
2. Xcode项目配置修复
- 添加URL Scheme:在
Info.plist中添加CFBundleURLTypes数组,其中CFBundleURLSchemes包含你的Google Client ID的反向ID(即com.googleusercontent.apps.xxxxxxxxx,可从控制台复制) - 添加查询Scheme:在
Info.plist中添加LSApplicationQueriesSchemes数组,包含以下项:<string>google</string> <string>googleusercontent</string> - 启用Keychain Sharing:进入项目Target ->
Signing & Capabilities-> 点击+ Capability,添加Keychain Sharing,并添加团队ID前缀+Bundle ID的组(例如TEAMID.com.yourcompany.appname)
3. 代码逻辑优化
当前代码在viewDidLoad和signInPressed中重复调用googleSignIn,导致登录流程冲突,建议调整:
修改signInPressed方法
@IBAction func signInPressed(_ sender: UIButton) { print("Sign in pressed") let user = GIDSignIn.sharedInstance.currentUser if user == nil { // 直接发起新登录,跳过restore流程 let signInConfig = GIDConfiguration(clientID: K.clientID) GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { gUser, signInError in if signInError == nil { guard let gUser = gUser else { sender.setTitle("Sign in", for: .normal) return } self.requestScopes(googleUser: gUser) { success in sender.setTitle(success ? "Sign out" : "Sign in", for: .normal) } } else { print("error with signing in: \(String(describing: signInError)) ") self.service.authorizer = nil sender.setTitle("Sign in", for: .normal) } } } else { GIDSignIn.sharedInstance.signOut() self.service.authorizer = nil sender.setTitle("Sign in", for: .normal) } }
调整googleSignIn方法(仅用于恢复登录)
func googleSignIn(completionHandler: @escaping (Bool) -> Void) { GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in if let user = user { print("Managed to restore previous sign in!\nScopes: \(String(describing: user.grantedScopes))") self.requestScopes(googleUser: user) { success in completionHandler(success) } } else { print("No previous user!\nThis is the error: \(String(describing: error?.localizedDescription))") completionHandler(false) } } }
修复requestScopes中的认证逻辑
替换错误的user?.authentication.do写法:
func requestScopes(googleUser: GIDGoogleUser, completionHandler: @escaping (Bool) -> Void) { let grantedScopes = googleUser.grantedScopes if grantedScopes == nil || !grantedScopes!.contains(K.grantedScopes) { let additionalScopes = K.additionalScopes GIDSignIn.sharedInstance.addScopes(additionalScopes, presenting: self) { user, scopeError in if scopeError == nil, let user = user { // 正确获取认证信息 if let authentication = user.authentication { let authorizer = authentication.fetcherAuthorizer() self.service.authorizer = authorizer completionHandler(true) } else { print("Failed to get authentication") completionHandler(false) } } else { completionHandler(false) print("Error with adding scopes: \(String(describing: scopeError?.localizedDescription))") } } } else { print("Already contains the scopes!") // 直接设置授权器 if let authentication = googleUser.authentication { self.service.authorizer = authentication.fetcherAuthorizer() } completionHandler(true) } }
4. 模拟器测试注意事项
- 确保模拟器已登录Google账号(设置 -> 密码与账户 -> 添加Google账户)
- 若仍有问题,尝试使用真机测试,模拟器的钥匙链权限有时会有异常
内容的提问来源于stack exchange,提问作者user17792511
相关产品推荐
相关产品推荐

