淺談UIAlertView與UIAlertController

蘋果在iOS8.0后推出了UIAlertController以代替UIAlertView,導(dǎo)致的后果就是UIAlertView在iOS9.0之后被deprecated了,也就是iOS8.0之后只能用UIAlertController,iOS8.0之前只能用UIAlertView。所以如果想同時(shí)兼容iOS7和iOS8,就判斷一下系統(tǒng)的版本,demo代碼如下:

http://www.2cto.com/kf/201604/504142.html#)

if([[[UIDevice currentDevice] systemVersion] floatValue] >=8.0) {   
// for iOS8

     UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"是否結(jié)束行程?" message:nil preferredStyle:UIAlertControllerStyleAlert];

     UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

            [self.navigationController dismissViewController Animated:alertController completion:nil];    
     }];

     UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
         [self upload];
     }];

    [alertController addAction:cancelAction];        
    [alertController addAction:okAction];
    [self.navigationController presentViewController:alertController animated:YES completion:nil];
}else{
// for iOS7     

     self.uploadAlertView = [[UIAlertView alloc]  initWithTitle:@"是否結(jié)束行程?"   message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
   
    [self.uploadAlertView show];
}

if([[[UIDevice currentDevice] systemVersion] floatValue] >=8.0) {   
// for iOS8      
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"是否結(jié)束行程?" message:nil preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

        [self.navigationController dismissViewControllerAnimated:alertController completion:nil];    
    }];  

    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self upload];
    }];

    [alertController addAction:cancelAction];

    [alertController addAction:okAction];

    [self.navigationController presentViewController:alertController animated:YES completion:nil];
}else{

// for iOS7
    self.uploadAlertView = [[UIAlertView alloc] initWithTitle:@"是否結(jié)束行程?" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
    [self.uploadAlertView show];
}

if([[[UIDevice currentDevice] systemVersion] floatValue] >8.0) {    
// for iOS8 

 UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"是否結(jié)束行程?" message:nil preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消"style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

        [self.navigationController dismissViewControllerAnimated:alertController completion:nil];
    }];

    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action{          
        [self upload];        
    }];

    [alertController addAction:cancelAction];
    [alertController addAction:okAction];
    [self.navigationController presentViewController:alertController animated:YES completion:nil];
}else{
// for iOS7
     self.uploadAlertView = [[UIAlertView alloc] initWithTitle:@"是否結(jié)束行程?" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];      
     [self.uploadAlertView show];
}

if([[[UIDevice currentDevice] systemVersion] floatValue] >=8.0) {     
// for iOS8
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"是否結(jié)束行程?"message:nil preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

        [self.navigationController dismissViewControllerAnimated:alertController completion:nil];    
    }];

    
    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"確定"style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self upload];
    }];
    [alertController addAction:cancelAction];       
    [alertController addAction:okAction];
    [self.navigationController presentViewController:alertController animated:YES completion:nil];
 }else{  
// for iOS7
    self.uploadAlertView = [[UIAlertView alloc] initWithTitle:@"是否結(jié)束行程?" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];

     [self.uploadAlertView show];
}

if([[[UIDevice currentDevice] systemVersion] floatValue] >=8.0) {  
// for iOS8     

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"是否結(jié)束行程?" message:nil preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        self.navigationController dismissViewControllerAnimated:alertController completion:nil];
    }];

    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"確定"style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { self upload];}];
    [alertController addAction:cancelAction];
    [alertController addAction:okAction];
    [self.navigationController presentViewController:alertController animated:YES completion:nil];
}else{
// for iOS7
    
    self.uploadAlertView = [[UIAlertView alloc] initWithTitle:@"是否結(jié)束行程?" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
    [self.uploadAlertView show];
}

當(dāng)然蘋果其實(shí)沒有真正的把UIAlertView給deprecate掉,UIAlertView 在iOS8以后 可能會發(fā)生異常Bug而已。而且你也不知道它哪天真的就會把它給禁用了。所以最好還是做一下兼容判斷處理。
iOS 8的新特性之一就是讓接口更有適應(yīng)性、更靈活,因此許多視圖控制器的實(shí)現(xiàn)方式發(fā)生了巨大的變化。全新的UIPresentationController在實(shí)現(xiàn)視圖控制器間的過渡動畫效果和自適應(yīng)設(shè)備尺寸變化效果(比如說旋轉(zhuǎn))中發(fā)揮了重要的作用,它有效地節(jié)省了程序員們的工作量(天地良心啊)。還有,某些舊的UIKit控件也同樣發(fā)生了許多變化,比如說Alert Views、Action Sheets、Popovers以及Search Bar Controllers。本文將會對Alert Views和Action Sheets發(fā)生的改變進(jìn)行一個(gè)大致的介紹,我們會采用Objective-C和swift兩種語言同時(shí)進(jìn)行代碼說明。
UIAlertView
隨著蘋果上次iOS 5的發(fā)布,對話框視圖樣式出現(xiàn)在了我們面前,直到現(xiàn)在它都沒有發(fā)生過很大的變化。下面的代碼片段展示了如何初始化和顯示一個(gè)帶有“取消”和“好的”按鈕的對話框視圖。
Objective-C版本:

UIAlertView *alertview=[[UIAlertView alloc] initWithTitle:@"標(biāo)題" message:@ "這個(gè)是UIAlertView的默認(rèn)樣式" delegate:selfcancelButtonTitle:@ "取消" otherButtonTitles:@"好的",nil];

[alertviewshow];

swift版本和Objective-C版本不同,在swift中,alertView的初始化只允許創(chuàng)建擁有一個(gè)取消按鈕的對話框視圖。或許您可以看到帶有otherButtonTitles的init方法,但是很遺憾,這個(gè)方法是沒有辦法通過編譯的。

varalertView=UIAlertView(title:"標(biāo)題",message:"這個(gè)是UIAlertView的默認(rèn)樣式",delegate:self,cancelButtonTitle:"取消");

alertView.show()

要能夠創(chuàng)建和上面Objective-C版本相同的對話框視圖,我們可以采取曲線救國的方法,雖然麻煩了些,但是我們?yōu)榱四康目梢圆粨袷侄蔚模前桑?/p>

 varalertView=UIAlertView()
 alertView.delegate=self
alertView.title="標(biāo)題"
alertView.message="這個(gè)是UIAlertView的默認(rèn)樣式"
alertView.addButtonWithTitle("取消")
alertView.addButtonWithTitle("好的")
alertView.show()

您也可以通過更改UIAlertView的alertViewStyle屬性來實(shí)現(xiàn)輸入文字、密碼甚至登錄框的效果。

1416966945708911.png

UIAlertView文本對話框
1416966955321003.png

UIAlertView密碼對話框
1416966961499607.png

UIAlertView登錄對話框
UIAlertViewDelegate協(xié)議擁有響應(yīng)對話框視圖的按鈕動作的回調(diào)方法。還有當(dāng)文本框內(nèi)容改變時(shí),調(diào)用alertViewShouldEnableOtherButton:方法可以讓按鈕動態(tài)地可用或者不可用。
要說明一點(diǎn),蘋果官方現(xiàn)在并不提倡在iOS 8中使用UIAlertView,取而代之的是UIAlertController。下面我們就來介紹UIAlertController的使用方法。
UIAlertController
在iOS 8中,UIAlertController在功能上是和UIAlertView以及UIActionSheet相同的,UIAlertController以一種模塊化替換的方式來代替這兩貨的功能和作用。是使用對話框(alert)還是使用上拉菜單(action sheet),就取決于在創(chuàng)建控制器時(shí),您是如何設(shè)置首選樣式的。
一個(gè)簡單的對話框例子
您可以比較一下兩種不同的創(chuàng)建對話框的代碼,創(chuàng)建基礎(chǔ)UIAlertController的代碼和創(chuàng)建UIAlertView的代碼非常相似:
Objective-C版本:

UIAlertController *alertController[UIAlertController  alertControllerWithTitle:@"標(biāo)題" message:@"這個(gè)UIAlertController的默認(rèn)樣式" preferredStyle:UIAlertControllerStyleAlert];

swift版本:

varalertController=UIAlertController(title:"標(biāo)題",message:"這個(gè)是UIAlertController的默認(rèn)樣式",preferredStyle:UIAlertControllerStyle.Alert)

同創(chuàng)建UIAlertView相比,我們無需指定代理,也無需在初始化過程中指定按鈕。不過要特別注意第三個(gè)參數(shù),要確定您選擇的是對話框樣式還是上拉菜單樣式。
通過創(chuàng)建UIAlertAction的實(shí)例,您可以將動作按鈕添加到控制器上。UIAlertAction由標(biāo)題字符串、樣式以及當(dāng)用戶選中該動作時(shí)運(yùn)行的代碼塊組成。通過UIAlertActionStyle,您可以選擇如下三種動作樣式:常規(guī)(default)、取消(cancel)以及警示(destruective)。為了實(shí)現(xiàn)原來我們在創(chuàng)建UIAlertView時(shí)創(chuàng)建的按鈕效果,我們只需創(chuàng)建這兩個(gè)動作按鈕并將它們添加到控制器上即可。
Objective-C版本:

UIAlertAction*cancelAction=[UIAlertActionactionWithTitle:@"取消" style:UIAlertActionStyleCancelhandler:nil];
UIAlertAction*okAction=[UIAlertActionactionWithTitle:@"好的" style:UIAlertActionStyleDefaulthandler:nil];
[alertControlleraddAction:cancelAction];
[alertControlleraddAction:okAction];

swift版本:

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

varokAction=UIAlertAction(title:"好的",style:UIAlertActionStyle.Default,handler:nil) alertController.addAction(cancelAction) alertController.addAction(okAction)

最后,我們只需顯示這個(gè)對話框視圖控制器即可:
Objective-C版本:

[self presentViewController:alertController animated:YEScompletion:nil];

swift版本:

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

1416967052393203.png

默認(rèn)樣式
按鈕顯示的次序取決于它們添加到對話框控制器上的次序。一般來說,根據(jù)蘋果官方制定的《iOS 用戶界面指南》,在擁有兩個(gè)按鈕的對話框中,您應(yīng)當(dāng)將取消按鈕放在左邊。要注意,取消按鈕是唯一的,如果您添加了第二個(gè)取消按鈕,那么你就會得到如下的一個(gè)運(yùn)行時(shí)異常:
* Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘UIAlertController can only have one action with a style of UIAlertActionStyleCancel’
異常信息簡潔明了,我們在此就不贅述了。
“警示”樣式
什么是“警示”樣式呢?我們先不著急回答這個(gè)問題,先來看一下下面關(guān)于“警示”樣式的簡單示例。在這個(gè)示例中,我們將前面的示例中的“好的”按鈕替換為了“重置”按鈕。
Objective-C版本:

    UIAlertAction*resetAction=[UIAlertActionactionWithTitle:@"重置" style:UIAlertActionStyleDestructivehandler:nil];

    [alertControlleraddAction:resetAction];

swift版本:

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

alertController.addAction(resetAction)

1416967112867112.png

“警示”樣式
可以看出,我們新增的那個(gè)“重置”按鈕變成了紅色。根據(jù)蘋果官方的定義,“警示”樣式的按鈕是用在可能會改變或刪除數(shù)據(jù)的操作上。因此用了紅色的醒目標(biāo)識來警示用戶。
文本對話框
UIAlertController極大的靈活性意味著您不必拘泥于內(nèi)置樣式。以前我們只能在默認(rèn)視圖、文本框視圖、密碼框視圖、登錄和密碼輸入框視圖中選擇,現(xiàn)在我們可以向?qū)υ捒蛑刑砑尤我鈹?shù)目的UITextField對象,并且可以使用所有的UITextField特性。當(dāng)您向?qū)υ捒蚩刂破髦刑砑游谋究驎r(shí),您需要指定一個(gè)用來配置文本框的代碼塊。
舉個(gè)栗子吧,要重新建立原來的登錄和密碼樣式對話框,我們可以向其中添加兩個(gè)文本框,然后用合適的占位符來配置它們,最后將密碼輸入框設(shè)置使用安全文本輸入。
Objective-C版本:

UIAlertController *alertController [UIAlertController  alertControllerWithTitle:@"文本對話框"message:@"登錄和密碼對話框示例" preferredStyle:UIAlertControllerStyleAlert];

[alertControlleraddTextFieldWithConfigurationHandler:^(UITextField*textField){
    textField.placeholder=@"登錄";
 }];

[alertControlleraddTextFieldWithConfigurationHandler:^(UITextField*textField){
    textField.placeholder=@"密碼";
   textField.secureTextEntry=YES;
}];

swift版本:

alertController.addTextFieldWithConfigurationHandler{ (textField:UITextField!)->Voidin
    textField.placeholder="登錄"
}

alertController.addTextFieldWithConfigurationHandler{ (textField:UITextField!)->Voidin
    textField.placeholder="密碼"
    textField.secureTextEntry=true
}

在“好的”按鈕按下時(shí),我們讓程序讀取文本框中的值。
Objective-C版本:

UIAlertAction  *okAction=[UIAlertActionaction WithTitle:@"好的" style:UIAlertActionStyleDefaulthandler:^(UIAlertAction*action){
   UITextField *login=alertController.textFields.firstObject;
   UITextField*password=alertController.textFields.lastObject;
...
}];

swift版本:

varokAction=UIAlertAction(title:"好的", style:UIAlertActionStyle.Default){
    (action:UIAlertAction!)->Voidin
    varlogin=alertController.textFields?.firstasUITextField
    varpassword=alertController.textFields?.lastasUITextField
}

如果我們想要實(shí)現(xiàn)UIAlertView中的委托方法alertViewShouldEnableOtherButton:方法的話可能會有一些復(fù)雜。假定我們要讓“登錄”文本框中至少有3個(gè)字符才能激活“好的”按鈕。很遺憾的是,在UIAlertController中并沒有相應(yīng)的委托方法,因此我們需要向“登錄”文本框中添加一個(gè)Observer。Observer模式定義對象間的一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí), 所有依賴于它的對象都得到通知并被自動更新。我們可以在構(gòu)造代碼塊中添加如下的代碼片段來實(shí)現(xiàn)。
Objective-C版本:

[alertControlleraddTextFieldWithConfigurationHandler:^(UITextField*textField){

...

    [[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(alertTextFieldDidChange:)name:UITextFieldTextDidChangeNotificationobject:textField];

}];

swift版本:

alertController.addTextFieldWithConfigurationHandler{
    (textField:UITextField!)->Voidin
    ...

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

}

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

UIAlertAction *okAction=[UIAlertActionaction WithTitle:@"好的"    style:UIAlertActionStyleDefaulthandler:^(UIAlertAction*action){
...     
    [[NSNotificationCenterdefaultCenter]removeObserver:selfname:UITextFieldTextDidChangeNotificationobject:nil];
}];

swift版本:

varokAction=UIAlertAction(title:"好的",style:UIAlertActionStyle.Default){
(action:UIAlertAction!)->Voidin
...
NSNotificationCenter.defaultCenter().removeObserver(self,name:UITextFieldTextDidChangeNotification,object:nil)
}

在顯示對話框之前,我們要凍結(jié)“好的”按鈕
Objective-C版本:

okAction.enabled=NO;

swift版本:

okAction.enabled=false

接下來,在通知觀察者(notification observer)中,我們需要在激活按鈕狀態(tài)前檢查“登錄”文本框的內(nèi)容。
Objective-C版本:

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

funcalertTextFieldDidChange(notification:NSNotification){
    varalertController=self.presentedViewControllerasUIAlertController?

    if(alertController!=nil){
        varlogin=alertController!.textFields?.firstasUITextField
        varokAction=alertController!.actions.lastasUIAlertAction
       okAction.enabled=countElements(login.text)>2
     }
}

1416967618423000.png

UIAlertController的登錄和密碼對話框示例
好了,現(xiàn)在對話框的“好的”按鈕被凍結(jié)了,除非在“登錄”文本框中輸入3個(gè)以上的字符:
上拉菜單
當(dāng)需要給用戶展示一系列選擇的時(shí)候(選擇恐懼癥患者殺手),上拉菜單就能夠派上大用場了。和對話框不同,上拉菜單的展示形式和設(shè)備大小有關(guān)。在iPhone上(緊縮寬度),上拉菜單從屏幕底部升起。在iPad上(常規(guī)寬度),上拉菜單以彈出框的形式展現(xiàn)。
創(chuàng)建上拉菜單的方式和創(chuàng)建對話框的方式非常類似,唯一的區(qū)別是它們的形式。
Objective-C版本:

UIAlertControlle *alertController=[UIAlertController alertControllerWithTitle:@"保存或刪除數(shù)據(jù)" message:@"刪除數(shù)據(jù)將不可恢復(fù)"preferredStyle:UIAlertControllerStyleActionSheet];

swift版本:

varalertController=UIAlertController(title:"保存或刪除數(shù)據(jù)",message:"刪除數(shù)據(jù)將不可恢復(fù)",preferredStyle:UIAlertControllerStyle.ActionSheet)

添加按鈕動作的方式和對話框相同。
Objective-C版本:

UIAlertAction *cancelAction=[UIAlertActionaction WithTitle:@"取消" style:UIAlertActionStyleCancelhandler:nil];

UIAlertAction *deleteAction=[UIAlertActionaction WithTitle:@"刪除"style:UIAlertActionStyleDestructivehandler:nil];
UIAlertAction *archiveAction=[UIAlertActionactionWithTitle:@"保存" style:UIAlertActionStyleDefaulthandler:nil];
[alertControlleraddAction:cancelAction];
[alertControlleraddAction:deleteAction];
[alertControlleraddAction:archiveAction];

swift版本:

varcancelAction=UIAlertAction(title:"取消",style:UIAlertActionStyle.Cancel,handler:nil)
vardeleteAction=UIAlertAction(title:"刪除",style:UIAlertActionStyle.Destructive,handler:nil)
vararchiveAction=UIAlertAction(title:"保存" ,style:UIAlertActionStyle.Default,handler:nil)
alertController.addAction(cancelAction)
alertController.addAction(deleteAction)
alertController.addAction(archiveAction)

您不能在上拉菜單中添加文本框,如果您強(qiáng)行作死添加了文本框,那么就會榮幸地得到一個(gè)運(yùn)行時(shí)異常:

  • Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert’
    同樣,簡單的異常說明,我們也不多說了。
    接下來我們就可以在iPhone或者其他緊縮寬度的設(shè)備上展示了,不出我們所料,運(yùn)行得很成功。
    Objective-C版本:

      [self presentViewController:alertController animated:YEScompletion:nil];
    

swift版本:

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

iPhone上的上拉菜單效果
如果上拉菜單中有“取消”按鈕的話,那么它永遠(yuǎn)都會出現(xiàn)在菜單的底部,不管添加的次序是如何(就是這么任性)。其他的按鈕將會按照添加的次序從上往下依次顯示。《iOS 用戶界面指南》要求所有的“毀壞”樣式按鈕都必須排名第一(紅榜嘛,很好理解的,對不對?)。
別激動得太早,我們現(xiàn)在還有一個(gè)很嚴(yán)重的問題,這個(gè)問題隱藏得比較深。當(dāng)我們使用iPad或其他常規(guī)寬度的設(shè)備時(shí),就會得到一個(gè)運(yùn)行時(shí)異常:
Terminating app due to uncaught exception ‘NSGenericException’, reason: ‘UIPopoverPresentationController (<_uialertcontrolleractionsheetregularpresentationcontroller: 0x7fc619588110="">) should have a non-nil sourceView or barButtonItem set before the presentation occurs.’
就如我們之前所說,在常規(guī)寬度的設(shè)備上,上拉菜單是以彈出框的形式展現(xiàn)。彈出框必須要有一個(gè)能夠作為源視圖或者欄按鈕項(xiàng)目的描點(diǎn)(anchor point)。由于在本例中我們是使用了常規(guī)的UIButton來觸發(fā)上拉菜單的,因此我們就將其作為描點(diǎn)。
在iOS 8中我們不再需要小心翼翼地計(jì)算出彈出框的大小,UIAlertController將會根據(jù)設(shè)備大小自適應(yīng)彈出框的大小。并且在iPhone或者緊縮寬度的設(shè)備中它將會返回nil值。配置該彈出框的代碼如下:
Objective-C版本:

UIPopoverPresentationController*popover=alertController.popoverPresentationController;

if(popover){
 popover.sourceView=sender;
 popover.sourceRect=sender.bounds;
 popover.permittedArrowDirections=UIPopoverArrowDirectionAny;
 }

swift版本:

varpopover=alertController.popoverPresentationController

if(popover!=nil){
    popover?.sourceView=sender
    popover?.sourceRect=sender.bounds
    popover?.permittedArrowDirections=UIPopoverArrowDirection.Any
}

1416967530355906.png

iPad上的上拉菜單效果
UIPopoverPresentationController類同樣也是在iOS 8中新出現(xiàn)的類,用來替換UIPopoverController的。這個(gè)時(shí)候上拉菜單是以一個(gè)固定在源按鈕上的彈出框的形式顯示的。
要注意UIAlertController在使用彈出框的時(shí)候自動移除了取消按鈕。用戶通過點(diǎn)擊彈出框的外圍部分來實(shí)現(xiàn)取消操作,因此取消按鈕便不再必需。
釋放對話框控制器
通常情況下,當(dāng)用戶選中一個(gè)動作后對話框控制器將會自行釋放。不過您仍然可以在需要的時(shí)候以編程方式釋放它,就像釋放其他視圖控制器一樣。您應(yīng)當(dāng)在應(yīng)用程序轉(zhuǎn)至后臺運(yùn)行時(shí)移除對話框或者上拉菜單。假定我們正在監(jiān)聽UIApplicationDidEnterBackgroundNotification通知消息,我們可以在observer中釋放任何顯示出來的視圖控制器。(參考在viewDidLoad方法中設(shè)立observer的示例代碼)。
Objective-C版本:

-(void)didEnterBackground:(NSNotification*)notification{

    [[NSNotificationCenterdefaultCenter]removeObserver:selfname:UITextFieldTextDidChangeNotificationobject:nil];

    [self.presentedViewControllerdismissViewControllerAnimated:NOcompletion:nil];
}

swift版本:

funcdidEnterackground(notification:NSNotification){

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

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

}

注意,要保證運(yùn)行安全我們同樣要確保移除所有的文本框observer。
我們來總結(jié)一下
這篇文章比較長,但是希望能夠?qū)δ兴鶐椭T鹊腢IAlertView和UIActionSheet類仍然可以在iOS 8中工作得很好,所以沒有必要急于更換代碼(要知道本文用到的許多函數(shù)盡在iOS 8中支持)。本文的代碼可以在我的Github主頁上找到,包括了AlertController - ObjC以及AlertController - swift。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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