如何在不进行大量重构的前提下移除代码中废弃的UIAlertView?
第三种可行解决方案
可以通过给UIAlertController添加Objective-C分类(Category)的方式,封装和旧版UIAlertView一致的show方法,内部自动获取当前应用最顶层的视图控制器来执行present逻辑,既不需要大量重构现有业务代码,也不用每次手动获取VC。
分类实现代码
头文件 UIAlertController+Show.h
#import <UIKit/UIKit.h> @interface UIAlertController (Show) /// 直接弹出当前弹窗,用法和旧版UIAlertView的show完全一致 - (void)show; /// 快速弹出只有确认按钮的普通提示弹窗 + (void)showAlertWithTitle:(NSString *)title message:(NSString *)message confirmTitle:(NSString *)confirmTitle; @end
实现文件 UIAlertController+Show.m
#import "UIAlertController+Show.h" @implementation UIAlertController (Show) // 内部工具方法:获取当前应用最顶层的可present视图控制器 + (UIViewController *)topmostViewController { UIViewController *topVC = [[[UIApplication sharedApplication] delegate] window].rootViewController; while (topVC.presentedViewController) { // 跳过正在销毁的控制器,避免present报错 if (topVC.presentedViewController.isBeingDismissed) break; // 适配容器控制器 if ([topVC.presentedViewController isKindOfClass:[UINavigationController class]]) { topVC = [(UINavigationController *)topVC.presentedViewController topViewController]; } else if ([topVC.presentedViewController isKindOfClass:[UITabBarController class]]) { topVC = [(UITabBarController *)topVC.presentedViewController selectedViewController]; } else { topVC = topVC.presentedViewController; } } return topVC; } - (void)show { [[UIAlertController topmostViewController] presentViewController:self animated:YES completion:nil]; } + (void)showAlertWithTitle:(NSString *)title message:(NSString *)message confirmTitle:(NSString *)confirmTitle { UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:confirmTitle style:UIAlertActionStyleDefault handler:nil]]; [alert show]; } @end
改造后用法
原有旧代码:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"操作成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil]; [alert show];
替换后仅需修改少量代码,不需要调整业务上下文:
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"操作成功" preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]]; [alert show];
简单提示弹窗甚至可以用一行代码完成:
[UIAlertController showAlertWithTitle:@"提示" message:@"操作成功" confirmTitle:@"确定"];
苹果废弃UIAlertView的原因
- 设计规范统一:
UIAlertView是UIView子类,独立于UIKit的视图控制器体系之外,直接挂载到系统window上,不符合MVC设计规范,视图的展示逻辑不归属于对应的视图控制器管控。而UIAlertController完全遵循视图控制器的管理规则,所有转场、层级、生命周期都和普通VC一致,降低系统维护成本。 - 解决历史遗留问题:
UIAlertView存在大量已知问题,比如横竖屏旋转适配异常、和其他自定义弹窗/系统弹窗的层级冲突、代理回调容易产生野指针崩溃、无法自定义弹窗内容和动画效果等,这些问题在旧的实现框架下很难彻底修复。 - API复用性提升:
UIAlertController同时支持弹窗(Alert)和底部操作表(ActionSheet)两种样式,只需要修改preferredStyle参数即可切换,不需要再维护UIAlertView和UIActionSheet两套完全独立的API,降低开发者的学习成本和系统的维护成本。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

