當(dāng)你的應(yīng)用程序需要向用戶呈現(xiàn)重要信息,或提示用戶重要選擇時,可以使用警告框(Alert View)和操作表(Action Sheet)。下圖左側(cè)部分是警告框,右側(cè)部分是操作表言询。
Alert&ActionSheet.png
自iOS 8開始,Apple用繼承自UIViewController的UIAlertController取代了UIAlertView和UIAlertSheet傲宜。
警報控制器(UIAlertController)雖然有警告框和操作表兩種形式运杭,但其創(chuàng)建步驟是一樣的。如下所示:
創(chuàng)建UIAlertController函卒,指定警報控制器樣式辆憔。
向警報控制器添加按鈕。
顯示UIAlertController报嵌。
1. 創(chuàng)建demo
下面通過demo來學(xué)習(xí)一下虱咧。
打開Xcode,點(diǎn)擊File > New > Project…锚国,選擇iOS > Application > Single View Application模板腕巡,點(diǎn)擊Next;在Product Name中填寫AlertController血筑,點(diǎn)擊Next绘沉;選擇文件,點(diǎn)擊Create創(chuàng)建工程豺总。
打開剛創(chuàng)建工程的storyboard车伞,在storyboard中自上而下依次添加以下控件,內(nèi)容為UIAlertControllerStyleAlert的UILabel喻喳,名稱為Show Alert的UIButton另玖,名稱為Login Alert的UIButton,內(nèi)容為UIAlertControllerStyleActionSheet的UILabel沸枯,名稱為Action Sheet的UIButton。如下圖:
AlertControllerStoryboard.png
把UIButton拖拽到ViewController.m的接口部分赂弓,類型為IBAction绑榴。完成后代碼如下:
#import"ViewController.h"@interfaceViewController()- (IBAction)showAlertView:(UIButton*)sender;- (IBAction)showLoginAlertView:(UIButton*)sender;- (IBAction)showActionSheet:(UIButton*)sender;@end
2. 簡單對話框樣式
2.1 創(chuàng)建警報控制器
創(chuàng)建UIAlertController非常簡單,不需要設(shè)置代理盈魁、不需要指定按鈕翔怎。
下面先在showAlertView:方法中,創(chuàng)建UIAlertController。
- (IBAction)showAlertView:(UIButton*)sender{// 1.創(chuàng)建UIAlertControllerUIAlertController*alertController = [UIAlertControlleralertControllerWithTitle:@"Alert Title"message:@"The message is ..."preferredStyle:UIAlertControllerStyleAlert];}
這里的preferredStyle:參數(shù)有UIAlertControllerStyleAlert和UIAlertControllerStyleActionSheet兩種赤套,這里我們要創(chuàng)建的是Alert View飘痛,所以使用第一種。
2.2 添加按鈕
使用actionWithTitle: style: handler:方法創(chuàng)建UIAlertAction對象容握,之后把對象添加到警報控制器宣脉。
UIAlertAction對象由標(biāo)題、樣式和用戶單擊該按鈕時運(yùn)行的代碼塊三部分組成剔氏。UIAlertActionStyle有三種樣式塑猖,樣式一UIAlertActionStyleCancel,用于取消操作谈跛、不作任何修改羊苟,就是常見的取消按鈕;樣式二UIAlertActionStyleDefault感憾,按鈕的默認(rèn)樣式蜡励;第三種是UIAlertActionStyleDestructive,用于對數(shù)據(jù)進(jìn)行更改或刪除的操作阻桅,這種樣式的按鈕標(biāo)題會自動使用紅色顯示凉倚。
在showAlertView:方法中添加Cancel按鈕和OK按鈕。
- (IBAction)showAlertView:(UIButton*)sender{? ? ...// 2.創(chuàng)建并添加按鈕UIAlertAction*okAction = [UIAlertActionactionWithTitle:@"OK"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction* _Nonnull action) {NSLog(@"OK Action");? ? }];UIAlertAction*cancelAction = [UIAlertActionactionWithTitle:@"Cancel"style:UIAlertActionStyleCancelhandler:^(UIAlertAction* _Nonnull action) {NSLog(@"Cancel Action");? ? }];? ? [alertController addAction:okAction];// A[alertController addAction:cancelAction];// B}
2.3 顯示UIAlertController
顯示UIAlertController鳍刷。
- (IBAction)showAlertView:(UIButton*)sender{? ? ...// 3.呈現(xiàn)UIAlertContorller[selfpresentViewController:alertController animated:YEScompletion:nil];}
點(diǎn)擊Show Alert按鈕占遥,視圖控制器顯示如下:
AlertControllerAlertDefault.png
改變上面addAction:方法順序,運(yùn)行app输瓜,你會發(fā)現(xiàn)Alert View中按鈕順序不變瓦胎。當(dāng)Alert View樣式中有Cancel按鈕時,Cancel按鈕總是顯示在左側(cè)尤揣,與添加按鈕的順序無關(guān)搔啊。
在showAlertView:方法中再添加一個UIAlertActionStyleDestructive樣式的Reset按鈕。
- (IBAction)showAlertView:(UIButton*)sender{? ? ...UIAlertAction*resetAction = [UIAlertActionactionWithTitle:@"Reset"style:UIAlertActionStyleDestructivehandler:^(UIAlertAction* _Nonnull action) {NSLog(@"Reset Action");? ? }];? ? [alertController addAction:resetAction];// C[alertController addAction:okAction];// A[alertController addAction:cancelAction];// B...}
運(yùn)行demo北戏,顯示如下:
AlertControllerDestructive.png
當(dāng)Alert View中存在一個或兩個按鈕時负芋,按鈕會水平排布;按鈕大于兩個時會像Action Sheet那樣豎列展示嗜愈。把上面addAction:方法順序改變?yōu)锽旧蛾、A、C蠕嫁,運(yùn)行app锨天,視圖控制器顯示如下:
AlertBAC.png
可以看到只要上面有UIAlertActionStyleCancel樣式的按鈕,該按鈕總是在最底部剃毒,其他按鈕順序由添加順序決定病袄。如果包含UIAlertActionStyleDestructive樣式的按鈕搂赋,一般先添加,以便在第一個位置顯示益缠。每一個警報控制器只能包含一個Cancel按鈕脑奠,如果你添加了兩個或多個,在運(yùn)行時會拋出NSInternalInconsistencyException的異常幅慌。
3. 登錄文本框
UIAlerController的另一個用途是我們可以向警報控制器中添加任意數(shù)量的UITextField作為警報控制器內(nèi)容視圖中的一部分宋欺。比如常見的登陸框。
AlertControllerLoginDemo.png
為創(chuàng)建一個如上圖的登錄框欠痴,我們需要為警報控制器添加兩個文本框迄靠。每一個文本框添加合適的占位符以提示需要輸入文本信息類型,并為需要輸入密碼的文本框啟用安全文本喇辽,以確保密碼安全掌挚。更新后的showLoginAlertView:代碼如下:
- (IBAction)showLoginAlertView:(UIButton*)sender{// 1.創(chuàng)建UIAlertControllerUIAlertController*alertController = [UIAlertControlleralertControllerWithTitle:@"Login"message:@"Enter Your Account Info Below"preferredStyle:UIAlertControllerStyleAlert];// 2.1 添加文本框[alertController addTextFieldWithConfigurationHandler:^(UITextField* _Nonnull textField) {? ? ? ? textField.placeholder =@"username";? ? }];? ? [alertController addTextFieldWithConfigurationHandler:^(UITextField* _Nonnull textField) {? ? ? ? textField.placeholder =@"password";? ? ? ? textField.secureTextEntry =YES;? ? }];}
繼續(xù)在showLoginAlertView:方法中添加Cancel按鈕和Login按鈕,在點(diǎn)擊Login按鈕時獲取文本框中的賬號和密碼并輸出到控制臺菩咨。
- (IBAction)showLoginAlertView:(UIButton*)sender{? ? ...// 2.2? 創(chuàng)建Cancel Login按鈕UIAlertAction*cancelAction = [UIAlertActionactionWithTitle:@"Cancel"style:UIAlertActionStyleCancelhandler:^(UIAlertAction* _Nonnull action) {NSLog(@"Cancel Action");? ? }];UIAlertAction*loginAction = [UIAlertActionactionWithTitle:@"Login"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction* _Nonnull action) {UITextField*userName = alertController.textFields.firstObject;UITextField*password = alertController.textFields.lastObject;// 輸出用戶名 密碼到控制臺NSLog(@"username is %@, password is %@",userName.text,password.text);? ? }];}
上面的代碼中吠式,UIAlertController內(nèi)textFields數(shù)組內(nèi)元素順序和添加順序一致。
最后添加按鈕抽米,顯示警報控制器特占。
- (IBAction)showLoginAlertView:(UIButton*)sender{? ? ...// 2.3 添加按鈕[alertController addAction:cancelAction];? ? [alertController addAction:loginAction];// 3.顯示警報控制器[selfpresentViewController:alertController animated:YEScompletion:nil];}
現(xiàn)在運(yùn)行app,在第一個文本框中輸入pro648云茸,在第二個文本框內(nèi)輸入x是目,點(diǎn)擊Login按鈕,控制臺輸出如下:
usernameispro648, passwordisx
在實(shí)際應(yīng)用中我們一般會對用戶名和密碼長度進(jìn)行限制标捺,當(dāng)長度不足時應(yīng)該禁用Login按鈕懊纳。我們可以通過為文本框添加一個UIControllEventEditingChanged響應(yīng)事件來實(shí)現(xiàn)。記得在添加按鈕前先禁用按鈕亡容。更新后代碼如下:
- (IBAction)showLoginAlertView:(UIButton*)sender{? ? ...// 2.1 添加文本框[alertController addTextFieldWithConfigurationHandler:^(UITextField* _Nonnull textField) {? ? ? ? textField.placeholder =@"username";? ? ? ? ? ? ? ? [textField addTarget:selfaction:@selector(alertUserAccountInfoDidChange:) forControlEvents:UIControlEventEditingChanged];// 添加響應(yīng)事件}];? ? [alertController addTextFieldWithConfigurationHandler:^(UITextField* _Nonnull textField) {? ? ? ? textField.placeholder =@"password";? ? ? ? textField.secureTextEntry =YES;? ? ? ? ? ? ? ? [textField addTarget:selfaction:@selector(alertUserAccountInfoDidChange:) forControlEvents:UIControlEventEditingChanged];// 添加響應(yīng)事件}];? ? ? ? ...// 2.3 添加按鈕loginAction.enabled =NO;// 禁用Login按鈕[alertController addAction:cancelAction];? ? [alertController addAction:loginAction];? ? ...}- (void)alertUserAccountInfoDidChange:(UITextField*)sender{UIAlertController*alertController = (UIAlertController*)self.presentedViewController;if(alertController)? ? {NSString*userName = alertController.textFields.firstObject.text;NSString*password = alertController.textFields.lastObject.text;UIAlertAction*loginAction = alertController.actions.lastObject;if(userName.length >3&& password.length >6)// 用戶名大于3位嗤疯,密碼大于6位時,啟用Login按鈕闺兢。loginAction.enabled =YES;else// 用戶名小于等于3位茂缚,密碼小于等于6位,禁用Login按鈕屋谭。loginAction.enabled =NO;? ? }}
UIAlertController中的textFields和actions均是數(shù)組類型脚囊,添加的第一個對象index為0。之后按照添加的順序index依次加1桐磁,雖然前面說到Cancel按鈕一般顯示在左側(cè)(橫排)或底部(豎排)悔耘,但并不代表它在數(shù)組中的位置是第一個或最后一個,其index是由添加的順序決定所意。你可以根據(jù)username字符串長度來禁用Login按鈕進(jìn)行測試淮逊。
現(xiàn)在只有在用戶名大于三位、密碼大于六位時扶踊,Login按鈕才可以點(diǎn)擊泄鹏。
AlertControllerLoginA.png
AlertControllerLoginB.png
4. 操作表Action Sheet
操作表一般用于為用戶提供一組可供選擇的操作選項,如刪除秧耗、恢復(fù)等备籽。一般根據(jù)設(shè)備尺寸大小決定呈現(xiàn)形式,在iPhone上分井,操作表由底部滑出车猬;在iPad上,操作表以彈出框(popover)形式出現(xiàn)尺锚。
創(chuàng)建操作表的方法與警告框類似珠闰,唯一不同在于preferredStyle:參數(shù)的選擇。在showActionSheet:方法中創(chuàng)建操作表瘫辩。
- (IBAction)showActionSheet:(UIButton*)sender{// 1.創(chuàng)建UIAlertControllerUIAlertController*alertController = [UIAlertControlleralertControllerWithTitle:@"Action Sheet"message:@"Deleted data can't be restored"preferredStyle:UIAlertControllerStyleActionSheet];}
下面創(chuàng)建并添加按鈕伏嗜,最后呈現(xiàn)警報控制器。
- (IBAction)showActionSheet:(UIButton*)sender{? ? ...// 2.1 創(chuàng)建按鈕UIAlertAction*deleteAction = [UIAlertActionactionWithTitle:@"Delete"style:UIAlertActionStyleDestructivehandler:^(UIAlertAction* _Nonnull action) {NSLog(@"Delete Action");? ? }];UIAlertAction*cancelAction = [UIAlertActionactionWithTitle:@"Cancel"style:UIAlertActionStyleCancelhandler:^(UIAlertAction* _Nonnull action) {NSLog(@"Cancel Action");? ? }];// 2.2 添加按鈕[alertController addAction:deleteAction];? ? [alertController addAction:cancelAction];// 3.顯示警報控制器[selfpresentViewController:alertController animated:YEScompletion:nil];}
運(yùn)行app伐厌,操作表展示如下:
AlertControllerActionSheetiPhone.png
如果Action Sheet中有取消按鈕承绸,取消按鈕每次都會在底部顯示,其他按鈕會按照添加的順序顯示挣轨。在Action Sheet內(nèi)不能添加文本框军熏。如果你添加了文本框,在運(yùn)行時會拋出下面的異常提醒:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert'
如上面說到的卷扮,在iPad中Action Sheet以彈出框的形式呈現(xiàn)荡澎。彈出框總是需要一個錨點(diǎn),錨點(diǎn)可以是源視圖画饥,也可以是按鈕衔瓮。在這個demo中,我們用按鈕觸發(fā)彈出框抖甘,所以這里將把按鈕作為錨點(diǎn)热鞍。showActionSheet:方法更新后如下:
- (IBAction)showActionSheet:(UIButton*)sender{? ? ...UIPopoverPresentationController*popover = alertController.popoverPresentationController;if(popover)? ? {? ? ? ? popover.sourceView = sender;? ? ? ? popover.sourceRect = sender.bounds;? ? ? ? popover.permittedArrowDirections =UIPopoverArrowDirectionAny;? ? }// 3.顯示警報控制器[selfpresentViewController:alertController animated:YEScompletion:nil];}
如果在iPad中沒有添加上面方法,運(yùn)行時會出現(xiàn)下面崩潰提示:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController () of style UIAlertControllerStyleActionSheet. The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem.? If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.'
現(xiàn)在衔彻,Action Sheet以觸發(fā)它的按鈕為錨點(diǎn)薇宠,以彈出框形式展現(xiàn)。
AlertControllerActionSheetiPad.png
當(dāng)Action Sheet以彈出框形式展現(xiàn)時艰额,UIKit會取消顯示Cancel按鈕澄港。此時,點(diǎn)擊popover以外任何區(qū)域和點(diǎn)擊Cancel按鈕效果一致柄沮,同時會調(diào)用取消按鈕的完成處理程序回梧。
5. 退出警報控制器
警報控制器會在用戶點(diǎn)擊按鈕后自動消失废岂,但在app進(jìn)入后臺時,警告框和選擇表并不會自動退出狱意。此時湖苞,我們需要通過代碼實(shí)現(xiàn)退出警報控制器。
在通知中心進(jìn)行注冊详囤,當(dāng)接收到app進(jìn)入后臺的通知時退出警報控制器财骨。更新后的viewDidLoad如下:
- (void)viewDidLoad{? ? [superviewDidLoad];// app 進(jìn)入后臺后隱藏警報控制器[[NSNotificationCenterdefaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotificationobject:nilqueue:nilusingBlock:^(NSNotification* _Nonnull note) {? ? ? ? [self.presentedViewController dismissViewControllerAnimated:YEScompletion:nil];? ? }];}- (void)dealloc{// 移除觀察者[[NSNotificationCenterdefaultCenter] removeObserver:selfname:UIApplicationDidEnterBackgroundNotificationobject:nil];}
最后一定記得移除觀察者,否則會引起崩潰藏姐。
總結(jié)
下面總結(jié)下Alert View和Action Sheet的異同隆箩。
警告框Alert View:
一般顯示在當(dāng)前視圖控制器的中心,點(diǎn)擊警告框以外區(qū)域不能隱藏警告控制器羔杨。
可以添加任意數(shù)量文本框捌臊。
有一個或兩個按鈕時,橫向排布兜材,如果有Cancel按鈕娃属,則Cancel按鈕顯示在左側(cè);有兩個以上按鈕時护姆,豎列排布矾端,如果有Cancel按鈕,則Cancel按鈕顯示在最底部卵皂。其他按鈕按照添加順序排布秩铆。
操作表Action Sheet:
在iPhone中自下而上滑出顯示在當(dāng)前控制器的底部,點(diǎn)擊action sheet以外區(qū)域可以隱藏UIAlertController灯变。
在iPad中以popover方式殴玛、以源視圖為錨點(diǎn)顯示,點(diǎn)擊選擇表以外的區(qū)域可以隱藏警告控制器添祸。
不能添加文本框滚粟。
按鈕豎列排布,在iPhone中刃泌,Cancel按鈕默認(rèn)在底部顯示凡壤;在iPad中,Cancel按鈕默認(rèn)不顯示耙替。
UIAlertController類只能原樣使用亚侠,不支持子類化。該類的視圖層次結(jié)構(gòu)是私有的俗扇,不能修改硝烂。最后,需要注意的是铜幽,警告框和操作表向用戶顯示信息時會中斷應(yīng)用的當(dāng)前流程滞谢,請只在需要的時候使用串稀,切勿濫用。
作者:pro648
鏈接:http://www.reibang.com/p/a5307dd8c424
來源:簡書
簡書著作權(quán)歸作者所有狮杨,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處厨诸。