集成Firebase GoogleSignIn时出现重复视图控制器弹窗及崩溃问题
排查Google登录重复弹出VC及返回崩溃问题
看起来你遇到了Google Sign-In集成时的两个棘手问题:点击登录按钮会弹出两个完全相同的视图控制器,返回时还会触发应用崩溃。咱们一步步拆解根源,给出针对性的修复方案:
一、重复弹出相同视图控制器的原因及修复
最常见的触发点是Google Sign-In的UI代理被重复设置,或者登录按钮的点击事件被重复绑定。结合你的代码来看,可能存在这些情况:
- 你可能在
AppDelegate或其他视图控制器中也设置了GIDSignIn的uiDelegate,导致登录流程被多次触发 GIDSignInButton本身自带登录触发逻辑,如果你的Storyboard里额外给它绑定了IBAction,会造成重复调用
修复步骤:
- 统一GIDSignIn的全局配置:推荐在
AppDelegate的启动方法里完成基础配置,视图控制器只负责处理登录后的回调:
// AppDelegate.m @import GoogleSignIn; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [FIRApp configure]; GIDSignIn *signIn = [GIDSignIn sharedInstance]; signIn.clientID = [FIRApp defaultApp].options.clientID; // 若登录回调在VC中处理,这里不要设置delegate return YES; }
- 移除GIDSignInButton的额外绑定:如果你的Storyboard里给
googleLoginButton加了自定义点击事件,直接删除——这个按钮会自动处理登录触发,不需要额外绑定。 - 在VC生命周期中管理UI代理:避免重复设置,同时防止VC被释放后代理仍指向它:
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [GIDSignIn sharedInstance].uiDelegate = self; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [GIDSignIn sharedInstance].uiDelegate = nil; // 离开页面时清空代理,避免野指针 }
二、返回视图控制器栈时崩溃的原因及修复
返回崩溃大概率是野指针问题:当你弹出登录页面后,原FifthViewController可能已经被释放,但GIDSignIn的代理还指向它,或者你的返回动画逻辑访问了已释放的视图对象。
修复步骤:
- 严格管理代理生命周期:上面提到的在
viewWillDisappear里设置uiDelegate = nil是关键,能避免VC被释放后,Google Sign-In的回调还试图访问它。 - 修正返回按钮的动画逻辑:你的
dismissViewControllerAnimated:方法里,在dismiss完成后还在修改_googleLoginBackButton的frame——此时VC已经被移除出视图栈,视图可能已被释放,访问它会触发崩溃:
- (IBAction)dismissViewControllerAnimated:(UIButton *)sender { [UIView animateWithDuration:0.2 animations:^ { _googleLoginBackButton.frame = CGRectMake(168, 700, 40, 40); } completion:^(BOOL finished) { [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; // 移除dismiss后的动画,此时VC已不在视图栈中,修改视图无意义且易崩溃 } ]; }
- 开启僵尸对象检测定位问题:在Xcode中打开
Edit Scheme -> Diagnostics,勾选Zombie Objects,运行后崩溃时会显示具体是哪个已释放的对象被访问,帮助精准定位。
三、额外的代码优化建议
- 避免在
viewDidLoad里直接设置frame布局,推荐使用Auto Layout,防止屏幕旋转或尺寸变化时布局错乱 - 按钮的高亮状态可以用
UIButton的setTitleColor:forState:或setBackgroundImage:forState:实现,比直接修改layer更简洁且符合iOS规范
内容的提问来源于stack exchange,提问作者user8490301
相关产品推荐
相关产品推荐

