UIAlertController

转自星夜暮晨的博客

对话框样式

1`创建Alert控制器

Objective-C版本:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"标题"message:@"这个是UIAlertController的默认样式"preferredStyle:UIAlertControllerStyleAlert];

swift版本:

var alertController = UIAlertController(title:"标题", message:"这个是UIAlertController的默认样式", preferredStyle:UIAlertControllerStyle.Alert

)

2`创建AlertAction实例并添加到控制器上

通过创建UIAlertAction的实例,您可以将动作按钮添加到控制器上。UIAlertAction由标题字符串、样式以及当用户选中该动作时运行的

代码块组成。通过UIAlertActionStyle,您可以选择如下三种动作样式:常规(default)、取消(cancel)以及警示(destruective)。

Objective-C版本:

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消"style:UIAlertActionStyleCancel handler:nil];

UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"好的"style:UIAlertActionStyleDefault handler:nil];

-------

[alertController addAction:cancelAction];

[alertController addAction:okAction];


swift版本:

var cancelAction = UIAlertAction(title:"取消", style: UIAlertActionStyle.Cancel, handler: nil)

var defaultAction = UIAlertAction(title:"好的", style: UIAlertActionStyle.Default, handler: nil)

--------

alertController.addAction(cancelAction)

alertController.addAction(okAction)

3`显示该对话框控制器

Objective-C版本:

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

swift版本:

self.presentViewController(alertController, animated:true, completion: nil)

对话框样式

按钮显示的次序取决于它们添加到对话框控制器上的次序。一般来说,根据苹果官方制定的《iOS 用户界面指南》,在拥有两个按钮的对话框中,您应当将取消按钮放在左边。要注意,取消按钮是唯一的,如果您添加了第二个取消按钮,那么你就会得到一个运行时异常。

“警示”样式

我们将前面的示例中的“好的”按钮替换为了“重置”按钮。

Objective-C版本:

UIAlertAction *resetAction = [UIAlertAction actionWithTitle:@"重置"style:UIAlertActionStyleDestructive handler:nil];

[alertController addAction:resetAction];


swift版本:

var resetAction = UIAlertAction(title:"重置", style: UIAlertActionStyle.Destructive, handler: nil)

alertController.addAction(resetAction)

警示样式

可以看出,我们新增的那个“重置”按钮变成了红色。根据苹果官方的定义,“警示”样式的按钮是用在可能会改变或删除数据的操作上。因此用了红色的醒目标识来警示用户。

文本对话框

UIAlertController极大的灵活性意味着您不必拘泥于内置样式。以前我们只能在默认视图、文本框视图、密码框视图、登录和密码输入框视图中选择,现在我们可以向对话框中添加任意数目的UITextField对象,并且可以使用所有的UITextField特性。

举个例子吧:

Objective-C版本:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"文本对话框"message:@"登录和密码对话框示例"preferredStyle:UIAlertControllerStyleAlert];

[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField){

textField.placeholder = @"登录";

}];

[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {

textField.placeholder = @"密码";

textField.secureTextEntry = YES;

}];


swift版本:

alertController.addTextFieldWithConfigurationHandler {

(textField: UITextField!) -> Void in

textField.placeholder ="登录"

}

alertController.addTextFieldWithConfigurationHandler {

(textField: UITextField!) -> Void in

textField.placeholder ="密码"

textField.secureTextEntry =true

}

在“好的”按钮按下后,让程序读取文本框中的值。

Objective-C版本:

UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"好的"style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {

UITextField *login = alertController.textFields.firstObject;

UITextField *password = alertController.textFields.lastObject;

NSLog(@"%@",login.text);

NSLog(@"%@",password.text);

}];


swift版本:

var defaultAction = UIAlertAction(title:"好的", style: UIAlertActionStyle.Default) {

(action: UIAlertAction!) -> Void in

var login = alertController.textFields?.first as UITextField

var password = alertController.textFields?.last as UITextField

}

假定我们要让“登录”文本框中至少有3个字符才能激活“好的”按钮。因此我们需要向“登录”文本框中添加一个Observer。Observer模式是定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。我们可以在构造代码块(添加UITextField控件)中添加如下的代码片段来实现。

Objective-C版本:

[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField)

{

...

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(alertTextFieldDidChange:) name:

UITextFieldTextDidChangeNotification object:textField];

}];

swift版本:

alertController.addTextFieldWithConfigurationHandler

 {

(textField: UITextField!) -> Void in

...

NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("alertTextFieldDidChange:"), name: 

UITextFieldTextDidChangeNotification, object: textField)

}

当视图控制器释放的时候我们需要移除这个Observer,我们通过在每个按钮动作的handler代码块(还有其他任何可能释放视图控制器的地方)中添加合适的代码来实现它。比如说在defaultAction这个按钮动作中:

Objective-C版本:

UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"好的"style:UIAlertActionStyleDefault handler:^(UIAlertAction *action)

{

...

[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];

}];


swift版本:

varokAction = UIAlertAction(title:"好的", style: UIAlertActionStyle.Default) {

(action: UIAlertAction!) -> Voidin

...

NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextFieldTextDidChangeNotification, object: nil)

}

在显示对话框之前,我们要冻结“好的”按钮

Objective-C版本:

defaultAction.enabled = NO;

swift版本:

defaultAction.enabled =false

接下来,在通知观察者(notification observer)中,我们需要在激活按钮状态前检查“登录”文本框的内容。

Objective-C版本:

- (void)alertTextFieldDidChange:(NSNotification *)notification

{

UIAlertController *alertController = (UIAlertController *)self.presentedViewController;

if(alertController) 

    {

UITextField *login = alertController.textFields.firstObject;

UIAlertAction *defaultAction = alertController.actions.lastObject;

defaultAction.enabled = login.text.length > 2;   

     }

}

swift版本:

func alertTextFieldDidChange(notification: NSNotification)

{

varalertController = self.presentedViewController as UIAlertController?

if(alertController != nil)

      {

varlogin = alertController!.textFields?.first as UITextField

varokAction = alertController!.actions.last as UIAlertAction

okAction.enabled = countElements(login.text) > 2

      }

}

UIAlertController的登录和密码对话框示例

好了,现在对话框的“好的”按钮被冻结了,除非在“登录”文本框中输入3个以上的字符

上拉菜单

当需要给用户展示一系列选择的时候,上拉菜单就能够派上大用场了。和对话框不同,上拉菜单的展示形式和设备大小有关。

在iPhone上(紧缩宽度),上拉菜单从屏幕底部升起。在iPad上(常规宽度),上拉菜单以弹出框的形式展现。

创建上拉菜单的方式和创建对话框的方式非常类似,唯一的区别是它们的形式。

Objective-C版本:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"保存或删除数据"message:@"删除数据将不可恢复"preferredStyle: UIAlertControllerStyleActionSheet];

swift版本:

var alertController = UIAlertController(title:"保存或删除数据", message:"删除数据将不可恢复", preferredStyle: UIAlertControllerStyle.ActionSheet)

添加按钮动作的方式和对话框相同。

Objective-C版本:

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版本:

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)

您不能在上拉菜单中添加文本框,如果您强行添加文本框,那么就会得到一个运行时异常。

Objective-C版本:

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

swift版本:

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版本:

UIPopoverPresentationController类同样也是在iOS 8中新出现的类,用来替换UIPopoverController的。这个时候上拉菜单是以一个固定在源按钮上的弹出框的形式显示的。

UIPopoverPresentationController *popover = alertController.popoverPresentationController;

if(popover){

popover.sourceView = sender;

popover.sourceRect = sender.bounds;

popover.permittedArrowDirections = UIPopoverArrowDirectionAny;

}

swift版本:

var popover = alertController.popoverPresentationController

if(popover != nil){

popover?.sourceView = sender

popover?.sourceRect = sender.bounds

popover?.permittedArrowDirections = UIPopoverArrowDirection.Any

}

iPad上的上拉菜单效果



要注意UIAlertController在使用弹出框的时候自动移除了取消按钮。用户通过点击弹出框的外围部分来实现取消操作,因此取消按钮便不再必需。

释放对话框控制器

通常情况下,当用户选中一个动作后对话框控制器将会自行释放。不过您仍然可以在需要的时候以编程方式释放它,就像释放其他视图控制器一样。您应当在应用程序转至后台运行时移除对话框或者上拉菜单。假定我们正在监听UIApplicationDidEnterBackgroundNotification通知消息,我们可以在observer中释放任何显示出来的视图控制器。(参考在viewDidLoad方法中设立observer的示例代码)。

Objective-C版本:

- (void)didEnterBackground:(NSNotification *)notification

{

[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];

[self.presentedViewController dismissViewControllerAnimated:NO completion:nil];

}

swift版本:

func didEnterackground(notification: NSNotification){

NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextFieldTextDidChangeNotification, object: nil)

self.presentedViewController?.dismissViewControllerAnimated(false, completion: nil)

}

注意,要保证运行安全我们同样要确保移除所有的文本框observer。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容