iOS--UIAlertView與UIAlertController和UIAlertAction之間的事兒,uialertaction

來源:互聯網
上載者:User

iOS--UIAlertView與UIAlertController和UIAlertAction之間的事兒,uialertaction
iOS 8的新特性之一就是讓介面更有適應性、更靈活,因此許多視圖控制器的實現方式發生了巨大的變化。全新的UIPresentationController在實現視圖控制器間的過渡動畫效果和自適應裝置尺寸變化效果(比如說旋轉)中發揮了重要的作用,它有效地節省了程式員們的工作量(天地良心啊)。還有,某些舊的UIKit控制項也同樣發生了許多變化,比如說Alert ViewsAction SheetsPopovers以及Search Bar Controllers。本文將會對Alert ViewsAction Sheets發生的改變進行一個大致的介紹,採用Objective-C

  • UIAlertView
隨著蘋果上次iOS 5的發布,對話方塊視圖樣式出現在了我們面前,直到現在它都沒有發生過很大的變化。下面的程式碼片段展示了如何初始化和顯示一個帶有“取消”和“好的”按鈕的對話方塊視圖。
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:@"標題" message:@"這個是UIAlertView的預設樣式" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"好的", nil];[alertview show];
                            UIAlertView的預設樣式

要能夠建立和上面相同的對話方塊視圖

var alertView = UIAlertView()alertView.delegate = selfalertView.title = "標題"alertView.message = "這個是UIAlertView的預設樣式"alertView.addButtonWithTitle("取消")alertView.addButtonWithTitle("好的")alertView.show()

您也可以通過更改UIAlertViewalertViewStyle屬性來實現輸入文字、密碼甚至登入框的效果。


                    UIAlertView文本對話方塊
                    UIAlertView密碼對話方塊
                    UIAlertView登入對話方塊

UIAlertViewDelegate協議擁有響應對話方塊視圖的按鈕動作的回調方法。還有當文字框內容改變時,調用alertViewShouldEnableOtherButton:方法可以讓按鈕動態地可用或者不可用。

要說明一點,蘋果官方現在並不提倡在iOS 8中使用UIAlertView,取而代之的是UIAlertController。下面我們就來介紹UIAlertController的使用方法。

  • UIAlertController

在iOS 8中,UIAlertController在功能上是和UIAlertView以及UIActionSheet相同的,UIAlertController以一種模組化替換的方式來代替這兩貨的功能和作用。是使用對話方塊(alert)還是使用上拉菜單(action sheet),就取決於在建立控制器時,您是如何設定首選樣式的。

  • 一個簡單的對話方塊例子

您可以比較一下兩種不同的建立對話方塊的代碼,建立基礎UIAlertController的代碼和建立UIAlertView的代碼非常相似:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"標題" message:@"這個是UIAlertController的預設樣式" preferredStyle:UIAlertControllerStyleAlert];

同建立UIAlertView相比,我們無需指定代理,也無需在初始化過程中指定按鈕。不過要特別注意第三個參數,要確定您選擇的是對話方塊樣式還是上拉菜單樣式。

通過建立UIAlertAction的執行個體,您可以將動作按鈕添加到控制器上。UIAlertAction由標題字串、樣式以及當使用者選中該動作時啟動並執行代碼塊組成。通過UIAlertActionStyle,您可以選擇如下三種動作樣式:常規(default)、取消(cancel)以及警示(destruective)。為了實現原來我們在建立UIAlertView時建立的按鈕效果,我們只需建立這兩個動作按鈕並將它們添加到控制器上即可。

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:nil];[alertController addAction:cancelAction];[alertController addAction:okAction];

最後,我們只需顯示這個對話方塊視圖控制器即可:

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

                     UIAlertController預設樣式

按鈕顯示的次序取決於它們添加到對話方塊控制器上的次序。一般來說,根據蘋果官方制定的《iOS 使用者介面指南》,在擁有兩個按鈕的對話方塊中,您應當將取消按鈕放在左邊。要注意,取消按鈕是唯一的,如果您添加了第二個取消按鈕,那麼你就會得到如下的一個運行時異常:

* Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘UIAlertController can only have one action with a style of UIAlertActionStyleCancel’

異常資訊簡潔明了,我們在此就不贅述了。

  • “警示”樣式

什麼是“警示”樣式呢?我們先不著急回答這個問題,先來看一下下面關於“警示”樣式的簡單樣本。在這個樣本中,我們將前面的樣本中的“好的”按鈕替換為了“重設”按鈕。

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

                                       “警示”樣式

可以看出,我們新增的那個“重設”按鈕變成了紅色。根據蘋果官方的定義,“警示”樣式的按鈕是用在可能會改變或刪除資料的操作上。因此用了紅色的醒目標識來警示使用者。

  • 文本對話方塊

UIAlertController極大的靈活性意味著您不必拘泥於內建樣式。以前我們只能在預設視圖、文字框視圖、密碼框視圖、登入和密碼輸入框視圖中選擇,現在我們可以向對話方塊中添加任意數目的UITextField對象,並且可以使用所有的UITextField特性。當您向對話方塊控制器中添加文字框時,您需要指定一個用來配置文字框的代碼塊。

舉個栗子吧,要重建立立原來的登入和密碼樣式對話方塊,我們可以向其中添加兩個文字框,然後用合適的預留位置來配置它們,最後將密碼輸入框設定使用安全文本輸入。

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"文本對話方塊" message:@"登入和密碼對話方塊樣本" preferredStyle:UIAlertControllerStyleAlert];[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField){    textField.placeholder = @"登入";}];[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {    textField.placeholder = @"密碼";    textField.secureTextEntry = YES;}];

在“好的”按鈕按下時,我們讓程式讀取文字框中的值。

UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {    UITextField *login = alertController.textFields.firstObject;    UITextField *password = alertController.textFields.lastObject;
   NSLog(@"帳號:%@",login.text);
   NSLog(@"密碼:%@",password.text);
}];

如果我們想要實現UIAlertView中的委託方法alertViewShouldEnableOtherButton:方法的話可能會有一些複雜。假定我們要讓“登入”文字框中至少有3個字元才能啟用“好的”按鈕。很遺憾的是,在UIAlertController中並沒有相應的委託方法,因此我們需要向“登入”文字框中添加一個Observer。Observer模式定義對象間的一對多的依賴關係,當一個對象的狀態發生改變時, 所有依賴於它的對象都得到通知並被自動更新。我們可以在構造代碼塊中添加如下的程式碼片段來實現。

[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField){    ...    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(alertTextFieldDidChange:) name:UITextFieldTextDidChangeNotification object:textField];}];

當視圖控制器釋放的時候我們需要移除這個Observer,我們通過在每個按鈕動作的handler代碼塊(還有其他任何可能釋放視圖控制器的地方)中添加合適的代碼來實現它。比如說在okAction這個按鈕動作中:

UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {    ...    [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];}];

在顯示對話方塊之前,我們要凍結“好的”按鈕

okAction.enabled = NO;
接下來,在通知觀察者(notification observer)中,我們需要在啟用按鈕狀態前檢查“登入”文字框的內容。
- (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;    }}

      UIAlertController的登入和密碼對話方塊樣本

好了,現在對話方塊的“好的”按鈕被凍結了,除非在“登入”文字框中輸入3個以上的字元:

  • 上拉菜單

當需要給使用者展示一系列選擇的時候(選擇恐懼症患者殺手),上拉菜單就能夠派上大用場了。和對話方塊不同,上拉菜單的展示形式和裝置大小有關。在iPhone上(緊縮寬度),上拉菜單從螢幕底部升起。在iPad上(常規寬度),上拉菜單以彈出框的形式展現。

建立上拉菜單的方式和建立對話方塊的方式非常類似,唯一的區別是它們的形式。

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"儲存或刪除資料" message:@"刪除資料將不可恢複" preferredStyle: UIAlertControllerStyleActionSheet];

添加按鈕動作的方式和對話方塊相同。

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];

您不能在上拉菜單中添加文字框,如果您強行作死添加了文字框,那麼就會榮幸地得到一個運行時異常:

* Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert’

同樣,簡單的異常說明,我們也不多說了。

接下來我們就可以在iPhone或者其他緊縮寬度的裝置上展示了,不出我們所料,運行得很成功。

[self presentViewController:alertController animated:YES 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值。配置該彈出框的代碼如下:

UIPopoverPresentationController *popover = alertController.popoverPresentationController;if (popover){    popover.sourceView = sender;    popover.sourceRect = sender.bounds;    popover.permittedArrowDirections = UIPopoverArrowDirectionAny;}

iPad上的上拉菜單效果,

UIPopoverPresentationController類同樣也是在iOS 8中新出現的類,用來替換UIPopoverController的。這個時候上拉菜單是以一個固定在源按鈕上的彈出框的形式顯示的。

要注意UIAlertController在使用彈出框的時候自動移除了取消按鈕。使用者通過點擊彈出框的外圍部分來實現取消操作,因此取消按鈕便不再必需。

  • 解除配置框控制器

通常情況下,當使用者選中一個動作後對話方塊控制器將會自行釋放。不過您仍然可以在需要的時候以編程方式釋放它,就像釋放其他視圖控制器一樣。您應當在應用程式轉至後台運行時移除對話方塊或者上拉菜單。假定我們正在監聽UIApplicationDidEnterBackgroundNotification通知訊息,我們可以在observer中釋放任何顯示出來的視圖控制器。(參考在viewDidLoad方法中設立observer的範例程式碼)。

- (void)didEnterBackground:(NSNotification *)notification{  [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];  [self.presentedViewController dismissViewControllerAnimated:NO completion:nil];}
注意,要保證運行安全我們同樣要確保移除所有的文字框observer。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.