UIAlertController的用法解析

iOS 8的新特性之一就是让接口更有适应性、更灵活,因此许多视图控制器的实现方式发生了巨大的变化,并且在某些旧的UIKit控件也同样发生了许多变化,往统一的方向发展,比如说Alert Views、Action Sheets、Popovers以及Search Bar Controllers。这里将会对Alert Views和Action Sheets发生的改变进行一个大致的介绍.

UIAlertView

随着苹果上次iOS 5的发布,对话框视图样式出现在了我们面前,直到现在它都没有发生过很大的变化。下面的代码片段展示了如何初始化和显示一个带有“取消”和“好的”按钮的对话框视图。

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"我是标题" message:@"我是传递的消息正文" delegate:self cancelButtonTitle:@"取消按钮" otherButtonTitles:@"确定按钮", nil];
    [alertView show];

展示效果

UIAlertController的用法解析_第1张图片
UIAlertView的默认样式.png

并且通过一系列的代理方法来处理按钮点击的事件


UIAlertController的用法解析_第2张图片
alertView代理方法.png

也可以通过更改UIAlertView的alertViewStyle属性来实现输入文字、密码,登录框的效果。

typedef NS_ENUM(NSInteger, UIAlertViewStyle) {
    UIAlertViewStyleDefault = 0, //默认效果
    UIAlertViewStyleSecureTextInput,//单行密文文本输入框
    UIAlertViewStylePlainTextInput,//单行普通文本输入框
    UIAlertViewStyleLoginAndPasswordInput//登录输入框
}

单行输入框效果

   alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
UIAlertController的用法解析_第3张图片
单行文本框.png

单行secure entry

alertView.alertViewStyle = UIAlertViewStyleSecureTextInput;
UIAlertController的用法解析_第4张图片
单行密文文本输入框.png

双行登录框效果

alertView.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
UIAlertController的用法解析_第5张图片
双行登录框效果.png

通过

- (nullable UITextField *)textFieldAtIndex:(NSInteger)textFieldIndex ;

这个方法可以拿到在index位置的文本输入框. 从而监听文本输入框的改变

    [alertView textFieldAtIndex:0];
    [alertView textFieldAtIndex:1];

UIActionSheet

展示效果是从屏幕的底部往上钻出1个可点击的表格,对于这个控件的使用与UIAlertView 基本类似

  UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"我是标题" delegate:self cancelButtonTitle:@"取消按钮" destructiveButtonTitle:@"确定按钮" otherButtonTitles:@"关闭", nil];
    [sheet showInView:self.view];
UIAlertController的用法解析_第6张图片
UIActionSheet.png

也有一系列的代理方法来处理点击按钮事件

    - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;
    - (void)actionSheetCancel:(UIActionSheet *)actionSheet;
    - (void)willPresentActionSheet:(UIActionSheet *)actionSheet ;
    - (void)didPresentActionSheet:(UIActionSheet *)actionSheet;
    - (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex;
    - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex;

要说明一点,苹果官方现在并不提倡在iOS 8后中使用UIAlertView(9.0废弃)和UIActionSheet(8.3废弃),取而代之的是UIAlertController。下面我们就来介绍UIAlertController的使用方法

UIAlertController

UIAlertController以一种模块化替换的方式来代替上面两个控件的功能和作用。是使用弹出对话框(alert)还是使用向上钻出的菜单(action sheet),就取决于在创建控制器时,是如何设置首选样式的。

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"我是标题" message:@"我是要传递的消息" preferredStyle:UIAlertControllerStyleActionSheet];

preferredStyle的枚举,通过指定样式来确定是以什么方法展示

    typedef NS_ENUM(NSInteger, UIAlertControllerStyle) {
        UIAlertControllerStyleActionSheet = 0,
        UIAlertControllerStyleAlert
    }

可以比较一下两种不同的创建对话框的代码,创建基础UIAlertController的代码和创建UIAlertView的代码非常相似:

由于创建出来的AlertController 变成了1个控制器 所以要使用modal的方式将控制器展示出来

  [self presentViewController:alertController animated:YES completion:nil];

如果仅仅是上面的两句代码 同创建UIAlertView相比,我们没有指定代理,也没有在初始化过程中指定按钮。那么控制器弹出后 没有任何按钮和文本输入框. 不过要特别注意第三个参数,要确定选择的是对话框样式还是向上钻的菜单样式


UIAlertController的用法解析_第7张图片
alert.png

UIAlertController的用法解析_第8张图片
actionSheet.png

接下来要往alertController中添加按钮或者文本输入框,通过创建UIAlertAction的实例,可以将动作按钮添加到控制器上。UIAlertAction由标题字符串、样式以及当用户选中该动作时运行的代码块组成。通过UIAlertActionStyle,您可以选择如下三种动作样式:常规(default)、取消(cancel)以及破坏性的,警示效果(destruective)[点击这个按钮一般要造成改变,所以按钮的样式系统默认会变为红色]。为了实现原来我们在创建UIAlertView时创建的按钮效果,我们只需创建两个动作按钮并将它们添加到控制器上即可。

按钮

typedef NS_ENUM(NSInteger, UIAlertActionStyle) {
    UIAlertActionStyleDefault = 0,//默认
    UIAlertActionStyleCancel,//取消  唯一
    UIAlertActionStyleDestructive//破坏性,警示效果按钮文字变成了红色。根据苹果官方的定义,“警示”样式的按钮是用在可能会改变或删除数据的操作上。因此用了红色的醒目标识来警示用户。
}
    UIAlertAction *CancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    
    UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        
    }];

样式如下


UIAlertController的用法解析_第9张图片
alertController.png

按钮显示的次序取决于它们添加到对话框控制器上的次序。一般来说,在拥有两个按钮的对话框中,您应当将取消按钮放在左边。要注意,取消按钮是唯一的,如果您添加了第二个取消按钮,那么你就会得到如下的一个运行时异常:
Terminating app due to uncaught exception
‘NSInternalInconsistencyException’, reason: ‘UIAlertController can only have one action with a style of UIAlertActionStyleCancel’

文本对话框

UIAlertController极大的灵活性意味着您不必拘泥于内置样式。以前我们只能在默认视图、文本框视图、密码框视图、登录和密码输入框视图中选择,现在我们可以向对话框中添加任意数目的UITextField对象,并且可以使用所有的UITextField特性。当您向对话框控制器中添加文本框时,您需要指定一个用来配置文本框的代码块
要重新建立原来的登录和密码样式对话框,我们可以向其中添加两个文本框,然后用合适的占位符来配置它们,最后将密码输入框设置使用安全文本输入。例如

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"我是标题" message:@"我是要传递的消息" preferredStyle:UIAlertControllerStyleActionSheet];
//取消按钮
UIAlertAction *CancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
    }];
//警示按钮
UIAlertAction *doneAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
    }];
//文本输入框
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        //配置文本框的代码块
        textField.placeholder = @"登录";
        textField.textColor = [UIColor greenColor];
    }];
    
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = @"密码";
        textField.secureTextEntry = YES;
    }];
    
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = @"打酱油的";
    }];
[alertController addAction:CancelAction];
[alertController addAction:doneAction];
[self presentViewController:alertController animated:YES completion:nil];

上面的例子添加了三个文本输入框 那么显示的效果就会变成这样


UIAlertController的用法解析_第10张图片
展示效果.png

但是如果试图向样式为actionSheet的alertController添加输入框,将会抛出异常:
Terminating app due to uncaught exception:
NSInternalInconsistencyException, reason: 'Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert'

在很多情况下 当我们点击确定按钮之后希望拿到文本框的值然后做一些事情.那么我们可以这样来操作
在 doneAction 创建的时候在代码块里面添加下面的代码 当点击确定按钮的时候 在控制台就会打印 在textField输入的值

UIAlertAction *doneAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        NSLog(@"%@--%@",alertController.textFields.firstObject.text,alertController.textFields.lastObject.text);
    }];

要注意的是,以上的写法是有问题的..由于在创建 doneAction 的时候 在block 里面 引用了 alertController 之后再将doneAction 添加到 alertController 里面. 那么将会产生循环引用导致alertController无法销毁.
所以此时应该这样做

   UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"我是标题" message:@"我是要传递的消息" preferredStyle:UIAlertControllerStyleAlert];
//避免产生循环引用问题
    __weak typeof(alertController) weakAlert = alertController;
    UIAlertAction *doneAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        NSLog(@"%@--%@",weakAlert.textFields.firstObject.text,weakAlert.textFields.lastObject.text);
    }];
  ........................
 [alertController addAction:doneAction];
 [self presentViewController:alertController animated:YES completion:nil];

如果需要监听文本输入框输入的改变.可以使用两种方式

  • 1 使用通知(需要在alertView 销毁的时候 ,移除通知 ,即在每个按钮动作的handler代码块中添加合适的代码来移除).
doneAction.enabled = NO;
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = @"登录";
        textField.textColor = [UIColor greenColor];
        //注册通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(accountTextFieldChange:) name:UITextFieldTextDidChangeNotification object:textField];
    }];
 - (void)accountTextFieldChange:(NSNotification *)notification{
//在这里拿到文本框
}

//移除通知

  __weak typeof(alertController) weakAlert = alertController;
    UIAlertAction *doneAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        
        NSLog(@"%@--%@",weakAlert.textFields.firstObject.text,weakAlert.textFields.lastObject.text);
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];
    }];

  • 2 使用addTarget(推荐使用这种方式.)
    举个栗子:当文本输入框里面的内容长度>3的时候才让确定按钮能够点击.
    首先要冻结 doneAction 按钮
doneAction.enabled = NO;
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = @"登录";
        textField.textColor = [UIColor greenColor];
 [textField addTarget:self action:@selector(accountTextFieldChange:) forControlEvents:UIControlEventEditingChanged];
- (void)accountTextFieldChange:(UITextField *)accountTextFiled{
    //获取alertController
    UIAlertController *alertController = (UIAlertController *)self.presentedViewController;
    //拿到doneAction按钮
    UIAlertAction * doneAction = alertController.actions[1];
//判断语句
    if (accountTextFiled.text.length >= 3) {
        doneAction.enabled = YES;
    }
UIAlertController的用法解析_第11张图片
确定按钮不可用.png
UIAlertController的用法解析_第12张图片
确定按钮可用.png

你可能感兴趣的:(UIAlertController的用法解析)