UIAlertController使用

當(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)并注明出處厨诸。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市禾酱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绘趋,老刑警劉巖颤陶,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異陷遮,居然都是意外死亡滓走,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門帽馋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搅方,“玉大人,你說我怎么就攤上這事绽族∫涛校” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵吧慢,是天一觀的道長涛漂。 經(jīng)常有香客問我,道長检诗,這世上最難降的妖魔是什么匈仗? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮逢慌,結(jié)果婚禮上悠轩,老公的妹妹穿的比我還像新娘。我一直安慰自己攻泼,他們只是感情好火架,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著忙菠,像睡著了一般距潘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上只搁,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天音比,我揣著相機(jī)與錄音,去河邊找鬼氢惋。 笑死洞翩,一個胖子當(dāng)著我的面吹牛稽犁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播骚亿,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼已亥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了来屠?” 一聲冷哼從身側(cè)響起虑椎,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎俱笛,沒想到半個月后捆姜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迎膜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年泥技,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磕仅。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡珊豹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出榕订,到底是詐尸還是另有隱情店茶,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布劫恒,位于F島的核電站忽妒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏兼贸。R本人自食惡果不足惜段直,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望溶诞。 院中可真熱鬧鸯檬,春花似錦、人聲如沸螺垢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枉圃。三九已至功茴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間孽亲,已是汗流浹背坎穿。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玲昧。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓栖茉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親孵延。 傳聞我的和親對象是個殘疾皇子吕漂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容