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。

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

推薦閱讀更多精彩內容