iOS简单调用系统提示框(UIAlertController)

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];

注意事项:

  1. 若需要界面显示时,就出现弹窗,建议在ViewDidAppear中调用。
  2. 设备是iOS9及之后版本的,同时弹出多个窗口时只会显示第一个,建议在cancelCallBack中多次弹出。
  3. 多个按钮的入参列表otherButtonTitles的顺序与otherCallBack中的返回的下标是一一对应的,从0开始。

Demo地址:
https://github.com/alanshen0118/ALAlertView.git

若有问题,小编会及时更正,请大家多多指教。
若觉得对您有用,请点下方喜欢,多谢支持~

Thanks~

你可能感兴趣的:(iOS简单调用系统提示框(UIAlertController))