UIAlertView和UIAlertController
UIAlertView
随着苹果上次iOS 5的发布,对话框视图样式出现在了我们面前,直到现在它都没有发生过很大的变化。下面的代码片段展示了如何初始化和显示一个带有“取消”和“好的”按钮的对话框视图。
Objective-C版本:
|
1
2
|
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"标题" message:@"这个是UIAlertView的默认样式" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"好的", nil];[alertview show]; |

UIAlertView的默认样式
swift版本和Objective-C版本不同,在swift中,alertView的初始化只允许创建拥有一个取消按钮的对话框视图。或许您可以看到带有otherButtonTitles的init方法,但是很遗憾,这个方法是没有办法通过编译的。
|
1
2
|
var alertView = UIAlertView(title: "标题", message: "这个是UIAlertView的默认样式", delegate: self, cancelButtonTitle: "取消")alertView.show() |

swift版本的UIAlertView
要能够创建和上面Objective-C版本相同的对话框视图,我们可以采取曲线救国的方法,虽然麻烦了些,但是我们为了目的可以不择手段的,是吧?
|
1
2
3
4
5
6
7
|
var alertView = UIAlertView()alertView.delegate = selfalertView.title = "标题"alertView.message = "这个是UIAlertView的默认样式"alertView.addButtonWithTitle("取消")alertView.addButtonWithTitle("好的")alertView.show() |
您也可以通过更改UIAlertView的alertViewStyle属性来实现输入文字、密码甚至登录框的效果。

UIAlertView文本对话框

UIAlertView密码对话框

UIAlertView登录对话框
UIAlertViewDelegate协议拥有响应对话框视图的按钮动作的回调方法。还有当文本框内容改变时,调用alertViewShouldEnableOtherButton:方法可以让按钮动态地可用或者不可用。
要说明一点,苹果官方现在并不提倡在iOS 8中使用UIAlertView,取而代之的是UIAlertController。下面我们就来介绍UIAlertController的使用方法。
UIAlertController
在iOS 8中,UIAlertController在功能上是和UIAlertView以及UIActionSheet相同的,UIAlertController以一种模块化替换的方式来代替这两货的功能和作用。是使用对话框(alert)还是使用上拉菜单(action sheet),就取决于在创建控制器时,您是如何设置首选样式的。
一个简单的对话框例子
您可以比较一下两种不同的创建对话框的代码,创建基础UIAlertController的代码和创建UIAlertView的代码非常相似:
Objective-C版本:
|
1
|
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"标题" message:@"这个是UIAlertController的默认样式" preferredStyle:UIAlertControllerStyleAlert]; |
swift版本:
|
1
|
var alertController = UIAlertController(title: "标题", message: "这个是UIAlertController的默认样式", preferredStyle: UIAlertControllerStyle.Alert) |
同创建UIAlertView相比,我们无需指定代理,也无需在初始化过程中指定按钮。不过要特别注意第三个参数,要确定您选择的是对话框样式还是上拉菜单样式。
通过创建UIAlertAction的实例,您可以将动作按钮添加到控制器上。UIAlertAction由标题字符串、样式以及当用户选中该动作时运行的代码块组成。通过UIAlertActionStyle,您可以选择如下三种动作样式:常规(default)、取消(cancel)以及警示(destruective)。为了实现原来我们在创建UIAlertView时创建的按钮效果,我们只需创建这两个动作按钮并将它们添加到控制器上即可。
Objective-C版本:
|
1
2
3
4
|
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:nil];[alertController addAction:cancelAction];[alertController addAction:okAction]; |
swift版本:
|
1
2
3
4
|
var cancelAction = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)var okAction = UIAlertAction(title: "好的", style: UIAlertActionStyle.Default, handler: nil)alertController.addAction(cancelAction)alertController.addAction(okAction) |
最后,我们只需显示这个对话框视图控制器即可:
Objective-C版本:
|
1
|
[self presentViewController:alertController animated:YES completion:nil]; |
swift版本:
|
1
|
self.presentViewController(alertController, animated: true, completion: nil) |

UIAlertController默认样式
按钮显示的次序取决于它们添加到对话框控制器上的次序。一般来说,根据苹果官方制定的《iOS 用户界面指南》,在拥有两个按钮的对话框中,您应当将取消按钮放在左边。要注意,取消按钮是唯一的,如果您添加了第二个取消按钮,那么你就会得到如下的一个运行时异常:
* Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘UIAlertController can only have one action with a style of UIAlertActionStyleCancel’
异常信息简洁明了,我们在此就不赘述了。
“警示”样式
什么是“警示”样式呢?我们先不着急回答这个问题,先来看一下下面关于“警示”样式的简单示例。在这个示例中,我们将前面的示例中的“好的”按钮替换为了“重置”按钮。
Objective-C版本:
|
1
2
|
UIAlertAction *resetAction = [UIAlertAction actionWithTitle:@"重置" style:UIAlertActionStyleDestructive handler:nil];[alertController addAction:resetAction]; |
swift版本:
|
1
2
|
var resetAction = UIAlertAction(title: "重置", style: UIAlertActionStyle.Destructive, handler: nil)alertController.addAction(resetAction) |

“警示”样式
可以看出,我们新增的那个“重置”按钮变成了红色。根据苹果官方的定义,“警示”样式的按钮是用在可能会改变或删除数据的操作上。因此用了红色的醒目标识来警示用户。
文本对话框
UIAlertController极大的灵活性意味着您不必拘泥于内置样式。以前我们只能在默认视图、文本框视图、密码框视图、登录和密码输入框视图中选择,现在我们可以向对话框中添加任意数目的UITextField对象,并且可以使用所有的UITextField特性。当您向对话框控制器中添加文本框时,您需要指定一个用来配置文本框的代码块。
举个栗子吧,要重新建立原来的登录和密码样式对话框,我们可以向其中添加两个文本框,然后用合适的占位符来配置它们,最后将密码输入框设置使用安全文本输入。
Objective-C版本:
|
1
2
3
4
5
6
7
8
|
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"文本对话框" message:@"登录和密码对话框示例" preferredStyle:UIAlertControllerStyleAlert];[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField){ textField.placeholder = @"登录";}];[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { textField.placeholder = @"密码"; textField.secureTextEntry = YES;}]; |
swift版本:
|
1
2
3
4
5
6
7
8
9
|
alertController.addTextFieldWithConfigurationHandler { (textField: UITextField!) -> Void in textField.placeholder = "登录"}alertController.addTextFieldWithConfigurationHandler { (textField: UITextField!) -> Void in textField.placeholder = "密码" textField.secureTextEntry = true} |
在“好的”按钮按下时,我们让程序读取文本框中的值。
Objective-C版本:
|
1
2
3
4
5
|
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { UITextField *login = alertController.textFields.firstObject; UITextField *password = alertController.textFields.lastObject; ...}]; |
swift版本:
|
1
2
3
4
5
|
var okAction = UIAlertAction(title: "好的", style: UIAlertActionStyle.Default) {(action: UIAlertAction!) -> Void in var login = alertController.textFields?.first as UITextField var password = alertController.textFields?.last as UITextField} |
如果我们想要实现UIAlertView中的委托方法alertViewShouldEnableOtherButton:方法的话可能会有一些复杂。假定我们要让“登录”文本框中至少有3个字符才能激活“好的”按钮。很遗憾的是,在UIAlertController中并没有相应的委托方法,因此我们需要向“登录”文本框中添加一个Observer。Observer模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。我们可以在构造代码块中添加如下的代码片段来实现。
Objective-C版本:
|
1
2
3
4
|
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField){ ... [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(alertTextFieldDidChange:) name:UITextFieldTextDidChangeNotification object:textField];}]; |
swift版本:
|
1
2
3
4
5
|
alertController.addTextFieldWithConfigurationHandler {(textField: UITextField!) -> Void in ... NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("alertTextFieldDidChange:"), name: UITextFieldTextDidChangeNotification, object: textField)} |
当视图控制器释放的时候我们需要移除这个Observer,我们通过在每个按钮动作的handler代码块(还有其他任何可能释放视图控制器的地方)中添加合适的代码来实现它。比如说在okAction这个按钮动作中:
Objective-C版本:
|
1
2
3
4
|
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { ... [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];}]; |
swift版本:
|
1
2
3
4
5
|
var okAction = UIAlertAction(title: "好的", style: UIAlertActionStyle.Default) {(action: UIAlertAction!) -> Void in ... NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextFieldTextDidChangeNotification, object: nil)} |
在显示对话框之前,我们要冻结“好的”按钮
Objective-C版本:
|
1
|
okAction.enabled = NO; |
swift版本:
|
1
|
okAction.enabled = false |
接下来,在通知观察者(notification observer)中,我们需要在激活按钮状态前检查“登录”文本框的内容。
Objective-C版本:
|
1
2
3
4
5
6
7
8
|
- (void)alertTextFieldDidChange:(NSNotification *)notification{ UIAlertController *alertController = (UIAlertController *)self.presentedViewController; if (alertController) { UITextField *login = alertController.textFields.firstObject; UIAlertAction *okAction = alertController.actions.lastObject; okAction.enabled = login.text.length > 2; }} |
swift版本:
|
1
2
3
4
5
6
7
8
|
func alertTextFieldDidChange(notification: NSNotification){ var alertController = self.presentedViewController as UIAlertController? if (alertController != nil) { var login = alertController!.textFields?.first as UITextField var okAction = alertController!.actions.last as UIAlertAction okAction.enabled = countElements(login.text) > 2 }} |

UIAlertController的登录和密码对话框示例
好了,现在对话框的“好的”按钮被冻结了,除非在“登录”文本框中输入3个以上的字符:
上拉菜单
当需要给用户展示一系列选择的时候(选择恐惧症患者杀手),上拉菜单就能够派上大用场了。和对话框不同,上拉菜单的展示形式和设备大小有关。在iPhone上(紧缩宽度),上拉菜单从屏幕底部升起。在iPad上(常规宽度),上拉菜单以弹出框的形式展现。
创建上拉菜单的方式和创建对话框的方式非常类似,唯一的区别是它们的形式。
Objective-C版本:
|
1
|
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"保存或删除数据" message:@"删除数据将不可恢复" preferredStyle: UIAlertControllerStyleActionSheet]; |
swift版本:
|
1
|
var alertController = UIAlertController(title: "保存或删除数据", message: "删除数据将不可恢复", preferredStyle: UIAlertControllerStyle.ActionSheet) |
添加按钮动作的方式和对话框相同。
Objective-C版本:
|
1
2
3
4
5
6
|
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];UIAlertAction *deleteAction = [UIAlertAction actionWithTitle:@"删除" style:UIAlertActionStyleDestructive handler:nil];UIAlertAction *archiveAction = [UIAlertAction actionWithTitle:@"保存" style:UIAlertActionStyleDefault handler:nil];[alertController addAction:cancelAction];[alertController addAction:deleteAction];[alertController addAction:archiveAction]; |
swift版本:
|
1
2
3
4
5
6
|
var cancelAction = UIAlertAction(title: "取消", style: UIAlertActionStyle.Cancel, handler: nil)var deleteAction = UIAlertAction(title: "删除", style: UIAlertActionStyle.Destructive, handler: nil)var archiveAction = UIAlertAction(title: "保存", style: UIAlertActionStyle.Default, handler: nil)alertController.addAction(cancelAction)alertController.addAction(deleteAction)alertController.addAction(archiveAction) |
您不能在上拉菜单中添加文本框,如果您强行作死添加了文本框,那么就会荣幸地得到一个运行时异常:
* Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert’
同样,简单的异常说明,我们也不多说了。
接下来我们就可以在iPhone或者其他紧缩宽度的设备上展示了,不出我们所料,运行得很成功。
Objective-C版本:
|
1
|
[self presentViewController:alertController animated:YES completion:nil]; |
swift版本:
|
1
|
self.presentViewController(alertController, animated: true, completion: nil) |

iPhone上的上拉菜单效果
如果上拉菜单中有“取消”按钮的话,那么它永远都会出现在菜单的底部,不管添加的次序是如何(就是这么任性)。其他的按钮将会按照添加的次序从上往下依次显示。《iOS 用户界面指南》要求所有的“毁坏”样式按钮都必须排名第一(红榜嘛,很好理解的,对不对?)。
别激动得太早,我们现在还有一个很严重的问题,这个问题隐藏得比较深。当我们使用iPad或其他常规宽度的设备时,就会得到一个运行时异常:
Terminating app due to uncaught exception ‘NSGenericException’, reason: ‘UIPopoverPresentationController (<_uialertcontrolleractionsheetregularpresentationcontroller: 0x7fc619588110="">) should have a non-nil sourceView or barButtonItem set before the presentation occurs.’
就如我们之前所说,在常规宽度的设备上,上拉菜单是以弹出框的形式展现。弹出框必须要有一个能够作为源视图或者栏按钮项目的描点(anchor point)。由于在本例中我们是使用了常规的UIButton来触发上拉菜单的,因此我们就将其作为描点。
在iOS 8中我们不再需要小心翼翼地计算出弹出框的大小,UIAlertController将会根据设备大小自适应弹出框的大小。并且在iPhone或者紧缩宽度的设备中它将会返回nil值。配置该弹出框的代码如下:
Objective-C版本:
|
1
2
3
4
5
6
|
UIPopoverPresentationController *popover = alertController.popoverPresentationController;if (popover){ popover.sourceView = sender; popover.sourceRect = sender.bounds; popover.permittedArrowDirections = UIPopoverArrowDirectionAny;} |
swift版本:
|
1
2
3
4
5
6
|
var popover = alertController.popoverPresentationControllerif (popover != nil){ popover?.sourceView = sender popover?.sourceRect = sender.bounds popover?.permittedArrowDirections = UIPopoverArrowDirection.Any} |

iPad上的上拉菜单效果
UIPopoverPresentationController类同样也是在iOS 8中新出现的类,用来替换UIPopoverController的。这个时候上拉菜单是以一个固定在源按钮上的弹出框的形式显示的。
要注意UIAlertController在使用弹出框的时候自动移除了取消按钮。用户通过点击弹出框的外围部分来实现取消操作,因此取消按钮便不再必需。
释放对话框控制器
通常情况下,当用户选中一个动作后对话框控制器将会自行释放。不过您仍然可以在需要的时候以编程方式释放它,就像释放其他视图控制器一样。您应当在应用程序转至后台运行时移除对话框或者上拉菜单。假定我们正在监听UIApplicationDidEnterBackgroundNotification通知消息,我们可以在observer中释放任何显示出来的视图控制器。(参考在viewDidLoad方法中设立observer的示例代码)。
Objective-C版本:
|
1
2
3
4
5
|
- (void)didEnterBackground:(NSNotification *)notification{ [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil]; [self.presentedViewController dismissViewControllerAnimated:NO completion:nil];} |
swift版本:
|
1
2
3
4
|
func didEnterackground(notification: NSNotification){ NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextFieldTextDidChangeNotification, object: nil) self.presentedViewController?.dismissViewControllerAnimated(false, completion: nil)} |
注意,要保证运行安全我们同样要确保移除所有的文本框observer。
我们来总结一下
这篇文章比较长,但是希望能够对您有所帮助。原先的UIAlertView和UIActionSheet类仍然可以在iOS 8中工作得很好,所以没有必要急于更换代码(要知道本文用到的许多函数尽在iOS 8中支持)。本文的代码可以在我的Github主页上找到,包括了AlertController - ObjC以及AlertController - swift。
UIAlertView和UIAlertController的更多相关文章
- iOS开发之UIAlertView与UIAlertController的详尽用法说明
本文将从四个方面对IOS开发中UIAlertView与UIAlertController的用法进行讲解: 一.UIAlertView与UIAlertController是什么东东? 二.我们为什么要用 ...
- 提示框(UIAlertController)的使用。
添加出现在屏幕中间的提示框(也就是之前的UIAlertView): UIAlertController * av = [UIAlertController alertControllerWithTit ...
- iOS学习——UIAlertController详解
在开发中,弹出提示框是必不可少的.这两天项目中统一对已经被iOS API废弃的UIAlertView和UIActionSheet进行替换,我们知道,UIAlertView和UIActionSheet都 ...
- SCLAlertView-Swift
SCLAlertView-Swift https://github.com/vikmeup/SCLAlertView-Swift Animated Alert View written in Sw ...
- Beginning iOS 8 Programming with Swift-TableView
UITableView控件使用 使用UITableView,在控件库中,拖拽一个Table View到ViewController中,在Controller的后台代码中需要继承UITableViewD ...
- iOS VIPER架构(三)
路由是实现模块间解耦的一个有效工具.如果要进行组件化开发,路由是必不可少的一部分.目前iOS上绝大部分的路由工具都是基于URL匹配的,优缺点都很明显.这篇文章里将会给出一个更加原生和安全的设计,这个设 ...
- ios9 之后,Xcode7不推荐使用UIAlertView,改用UIAlertController+UIAlertAction(按钮)
/** * ios9 之后,Xcode7不推荐使用UIAlertView,改用UIAlertController+UIAlertAction(按钮) */ UIAlertController *al ...
- ios-消息弹框之UIAlertView, UIActionSheet以及UIAlertController小结
首先storyboard中创建对应按钮并拖线,来演示不同的效果 首先点击了actionSheet按钮效果如图 实现弹框需要遵守设置代理,遵守协议. 效果就是从底部向上弹起来的框框. 通过对按钮的点击输 ...
- iOS - 提示信息 - UIAlertView、UIActionSheet、UIAlertController的实际应用
1.UIAlertView(屏幕中央弹出框)(不需要服从代理) UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@" ...
随机推荐
- ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)
在正式进入主题之前我们来看下几个概念: 一.依赖倒置 依赖倒置是编程五大原则之一,即: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象. 2.抽象不能依赖于具体,具体依赖于抽象. 其中上层就 ...
- golang-方法和接口
1.方法 方法类似函数 ,多了一个接收者 ,接收者是指针指向结构体(也可以是值) ,方法与结构体绑定 (可以理解为模板定义方法) ,方法位于结构体内部 方法集可以理解就是多个方法 可以组合其他结构体方 ...
- Spring Boot 2 构建可部署的war包
默认情况下Spring Boot使用了内嵌的Tomcat服务器,项目最终被打成jar包运行,每个jar包可以被看作一个独立的Web服务器.传统的Web开发,一般会将Web应用打成一个war包,然后将其 ...
- java最全的获取某个接口或者某个类所有对应的所有实现类和继承类的工具类--反射动态获取、非动态获取、按照路径获取等总结
我们直接上代码吧,代码中有注释说明. //直接看代码吧 import java.io.File; import java.lang.reflect.Field; import java.net.URL ...
- HTML5常见的取值与单位
HTML5常见的取值与单位 长度单位包括 相对长度单位包括:em, ex, ch, rem, vw, vh, vmax, vmin 绝对长度单位包括:cm, mm, q, in, pt, pc ...
- charles使用(安装、mock、限速、断点功能)
我们在进行B/S架构的Web项目开发时,在前端页面与后台交互的调试的时候,通常使用在JSP中加入“debugger;”断点,然后使用浏览器的F12开发者工具来查看可能出错的地方的数据.或者使用Http ...
- R1-5天
R语言笔记文档 2019.11.24 R语言的安装 工作目录查看与更改 变量的三种赋值 如何查看R语言帮助 ? args 基础数据类型 基本数据类型 因子.数据框.数组.矩阵.列表.向量 2019.1 ...
- a迭代中的燃尽图统计
简单分析:项目一直在跟进,进展较缓,临近迭代结束,项目进度突飞猛进.
- Python 生成器 (generator) & 迭代器 (iterator)
python 生成器 & 迭代器 生成器 (generator) 列表生成式 列表生成式用来生成一个列表,虽然写的是表达式,但是储存的是计算出来的结果,因此生成的列表受到内存大小的限制 示例: ...
- R-长尾词练习
一. 长尾关键词的特征 长尾关键词通常比较长,往往是2-3个词组成,甚至是短语,存在于内容页面,除了内容页的标题,还存在于内容中. 长尾关键词搜索量虽然非常少,而且不稳定.但是搜索量甚至超越热门目标关 ...