iOS9开始UIAlertView不被推荐使用,取而代之的是iOS8推出的UIAlertController。
从它们的命名就能看得出一个是继承了UIView,一个是继承了UIViewController。不少小伙伴看到这个变动后当场就不开心了。以前的UIAlertView到处可以调用,并且宏定义起来调用也非常方便。
#define Alert(msg) \
[[[UIAlertView alloc] initWithTitle:@"" \
message:msg \
delegate:nil \
cancelButtonTitle:@"确定" \
otherButtonTitles:nil, nil] show]; \
可是现在的UIAlertController是需要通过presentViewController来弹窗的,所以必须要拿到Controller才能调用,这样很不方便。让我们来看看有没有好的方法来改造一下呢。
要不来点简单粗暴的吧~
首先最最关键的就是获取当前显示的ViewController,也是顶层的ViewController。
#pragma mark - Utils
- (UIViewController *)getCurrentViewController
{
UIViewController *currentViewController = nil;
UIWindow * window = [[UIApplication sharedApplication] keyWindow];
if ([window subviews].count == 0) {
return nil;
}
if (window.windowLevel != UIWindowLevelNormal) {
NSArray *windows = [[UIApplication sharedApplication] windows];
for(UIWindow * subWindow in windows)
{
if (subWindow.windowLevel == UIWindowLevelNormal) {
window = subWindow;
break;
}
}
}
UIView *frontView = [[window subviews] objectAtIndex:0];
id nextResponder = [frontView nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
currentViewController = nextResponder;
} else {
currentViewController = window.rootViewController;
}
return currentViewController;
}
获取到当前的ViewController后,就可以配置UIAlertController进行跳转,方法命名模仿UIAlertView,并且用Block代替了UIAlertDelegate中的alertView:clickedButtonAtIndex:代理方法。
#pragma mark -- base method
/**
* 提示框基础方法
*
* @param title 标题
* @param message 消息
* @param cancelButtonTitle 取消按钮标题
* @param cancelCallBack 取消按钮回调
* @param otherCallBack 其他按钮回调
* @param otherButtonTitles 其他按钮
*/
- (void)showAlertViewWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle cancelCallBack:(CancelCallBack)cancelCallBack otherCallBack:(OtherCallBack)otherCallBack otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION{
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0
//初始化AlertController
UIAlertController *alertViewController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
//定义va_list
va_list argsList;
//指向首地址
va_start(argsList, otherButtonTitles);
NSInteger index = 0;
//遍历
while (otherButtonTitles) {
//过滤入参类型
if (![otherButtonTitles isKindOfClass:[NSString class]]) {
break;
}
//过滤空字符串
if (![self isBlankString:otherButtonTitles]) {
//添加提示框按钮动作
UIAlertAction *alertAction = [UIAlertAction actionWithTitle:otherButtonTitles style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (otherCallBack) {
[alertViewController dismissViewControllerAnimated:YES completion:nil];
otherCallBack(index);
}
}];
[alertViewController addAction:alertAction];
}
//指向下一个地址
otherButtonTitles = va_arg(argsList, NSString *);
index++;
}
va_end(argsList);
//取消按钮
if (![self isBlankString:cancelButtonTitle]) {
UIAlertAction *alertAction = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
//点击过后关闭提示框
if (cancelCallBack) {
[alertViewController dismissViewControllerAnimated:YES completion:nil];
//取消回调方法
cancelCallBack();
}
}];
[alertViewController addAction:alertAction];
}
//从当前控制器中模态弹出提示框
[[self getCurrentViewController] presentViewController:alertViewController animated:YES completion:nil];
#else
self.cancelCallBack = [cancelCallBack copy];
self.otherCallBack = [otherCallBack copy];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil];
va_list argsList;
va_start(argsList, otherButtonTitles);
NSInteger index = 0;
while (otherButtonTitles) {
if (![self isBlankString:otherButtonTitles]) {
[alertView addButtonWithTitle:otherButtonTitles];
}
otherButtonTitles = va_arg(argsList, NSString *);
index++;
}
va_end(argsList);
[alertView show];
}
常用的类方法以及对象方法也进行了浅层封装
+ (instancetype)alertView {
return [[[self class] alloc] init];
}
#pragma mark - public method
#pragma mark -- class method
/**
* 类方法 提示框(只显示消息)
*
* @param message 消息
*/
+ (void)showMessage:(NSString *)message {
[[[self class] alertView] showMessage:message];
}
/**
* 类方法 提示框(只显示标题和消息)
*
* @param title 标题
* @param message 消息
*/
+ (void)showAlertViewWithTitle:(NSString *)title message:(NSString *)message {
[[[self class] alertView] showAlertViewWithTitle:title message:message];
}
/**
* 类方法 提示框(只显示标题和消息)
*
* @param title 标题
* @param message 消息
* @param dismissCallBack 确定回调
*/
+ (void)showAlertViewWithTitle:(NSString *)title message:(NSString *)message dismissCallBack:(CancelCallBack)dismissCallBack {
[[[self class] alertView] showAlertViewWithTitle:title message:message dismissCallBack:dismissCallBack];
}
#pragma mark -- object method
/**
* 提示框(只显示消息)
*
* @param message 消息
*/
- (void)showMessage:(NSString *)message {
[self showAlertViewWithTitle:nil message:message];
}
/**
* 提示框(只显示标题和消息)
*
* @param title 标题
* @param message 消息
*/
- (void)showAlertViewWithTitle:(NSString *)title message:(NSString *)message {
[self showAlertViewWithTitle:title message:message cancelButtonTitle:@"确定" cancelCallBack:nil otherCallBack:nil otherButtonTitles:nil];
}
/**
* 提示框(只显示标题和消息)
*
* @param title 标题
* @param message 消息
* @param dismissCallBack 确定回调
*/
- (void)showAlertViewWithTitle:(NSString *)title message:(NSString *)message dismissCallBack:(CancelCallBack)dismissCallBack {
[self showAlertViewWithTitle:title message:message cancelButtonTitle:@"确定" cancelCallBack:dismissCallBack otherCallBack:nil otherButtonTitles:nil, nil];
}
至此,我们的目标也就达成了。我们可以用宏定义简单的调用系统提示框了
#define XXALERT(msg) [ALAlertView showMessage:msg];
注意事项:
- 若需要界面显示时,就出现弹窗,建议在ViewDidAppear中调用。
- 设备是iOS9及之后版本的,同时弹出多个窗口时只会显示第一个,建议在cancelCallBack中多次弹出。
- 多个按钮的入参列表otherButtonTitles的顺序与otherCallBack中的返回的下标是一一对应的,从0开始。
Demo地址:
https://github.com/alanshen0118/ALAlertView.git
若有问题,小编会及时更正,请大家多多指教。
若觉得对您有用,请点下方喜欢,多谢支持~
Thanks~