iOS中UIAlert关闭后界面无响应问题求助
iOS自动登出时关闭Alert导致界面无响应的解决建议
问题场景
- 5分钟无操作自动登出功能,无UIAlert弹窗时运行正常;
- 存在UIAlert弹窗时,登出后弹窗会残留到登录界面;
- 添加登出前关闭Alert的代码后,界面出现无响应,登录页输入框无法点击;
- 仅执行关闭Alert操作,也会导致当前页面无响应。
问题根源
你当前的dismissAnyAlertControllerIfPresent方法存在两个关键问题:
- 顶层控制器获取逻辑错误:直接从
keyWindow.rootViewController.presentedViewController开始遍历,若根VC没有presented控制器,topVC会直接为nil,后续调用dismiss会引发异常;同时嵌套弹窗场景下可能无法定位到真正的顶层Alert。 - UI操作未在主线程执行:自动登出逻辑大概率在子线程触发,直接调用UI操作会导致主线程混乱,引发界面无响应。
解决步骤
- 修正顶层VC遍历逻辑:从根VC开始完整遍历所有presented控制器,确保精准定位到顶层Alert;
- 强制主线程执行UI操作:所有弹窗关闭、页面跳转的UI操作必须放在主线程,避免线程冲突;
- 异步等待Alert关闭后跳转:利用
dismiss的completion回调,确保弹窗完全关闭后再执行登录页跳转,避免UI栈混乱。
修改后的代码
- (void)dismissAnyAlertControllerIfPresentWithCompletion:(void(^)(void))completion { // 强制在主线程处理UI操作 dispatch_async(dispatch_get_main_queue(), ^{ UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; UIViewController *currentVC = keyWindow.rootViewController; // 完整遍历所有presented控制器,找到顶层VC while (currentVC.presentedViewController) { currentVC = currentVC.presentedViewController; } if ([currentVC isKindOfClass:[UIAlertController class]]) { // 弹窗关闭完成后执行后续逻辑 [currentVC dismissViewControllerAnimated:NO completion:completion]; } else { // 无Alert直接执行回调 if (completion) { completion(); } } }); } - (void)didLogout { // 先关闭Alert,完成后再执行登出逻辑和页面跳转 [self dismissAnyAlertControllerIfPresentWithCompletion:^{ NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; [prefs removeObjectForKey:@"userName"]; [prefs synchronize]; [self redirectToLoginPage]; }]; } - (void)redirectToLoginPage { // 确保页面跳转在主线程执行 dispatch_async(dispatch_get_main_queue(), ^{ NSString *storyboardName = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone ? @"Main_iPhone" : @"Main_iPad"; UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil]; BmobileViewController *login = [storyboard instantiateViewControllerWithIdentifier:@"login"]; login.hideBackbtn = YES; login.hideAutoLogoutMsg = YES; login.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:login animated:YES completion:nil]; }); }
额外注意事项
- 检查自动登出的触发逻辑,确保所有UI相关操作都绑定到主线程;
- 如果登录页需要作为应用的起始页面,建议直接替换根控制器(
keyWindow.rootViewController = login),避免多层present导致的UI栈冗余; - 测试时可添加日志打印顶层VC的类名,确认是否正确定位到Alert控制器。
内容的提问来源于stack exchange,提问作者Bhuvi c
相关产品推荐
相关产品推荐

