iOS (封装)一句话调用系统的alertView和alertController
前言:
本文僅作參考存留,請用新版封裝:iOS 更加優(yōu)雅便捷的UIAlertView/UIAlertController封裝使用
UIAlertController是iOS8.0之后出來的新方法,其將系統(tǒng)原先的UIAlertView和UIActionSheet進行了規(guī)范整合。iOS9.0之后,UIAlertView和UIActionSheet已經(jīng)不建議使用,但還未徹底廢棄。
alert提示窗可以算得上是十分常用的UI控件了,基于上述情況,考慮到版本兼容,筆者將上述控件進行了簡單的整合封裝。
封裝之后,只需一句話,便可調(diào)用系統(tǒng)的alert提示,至于是調(diào)用alertView還是alertController,會根據(jù)系統(tǒng)版本自行判斷,做到了兼容適配。alert提示窗的回調(diào)方法,也基于block進行了封裝。按鈕數(shù)量提供了變參和數(shù)組兩種封裝模式,各有用途。
代碼見GitHub,已將這個較為簡單但個人感覺還算十分實用的庫進行了開源共享,喜歡的歡迎下載使用。
代碼可能還入不了大牛的眼,水平有限,還望見諒,也歡迎使用和反饋。
支持的多種效果展示
下面敘述一下封裝庫內(nèi)部分主要API的具體說明,代碼中也有較為詳細的注釋。
1.普通alert 變參 兼容適配alertView和alertController
/*** 普通alert定義 兼容適配alertView和alertController** @param viewController 當(dāng)前視圖,alertController模態(tài)彈出的指針* @param title 標題* @param message 詳細信息* @param block 用于執(zhí)行方法的回調(diào)block* @param cancelBtnTitle 取消按鈕,可為nil* @param destructiveBtn alertController的特殊按鈕類型,可為nil* @param otherButtonTitles 其他按鈕 變參量 但是按鈕類型的相對位置是固定的,可為nil * NS_REQUIRES_NIL_TERMINATION 是一個宏,用于編譯時非nil結(jié)尾的檢查 自動添加結(jié)尾的nil ***注意1*** //block方法序列號和按鈕名稱相同,按鈕類型排列順序固定 //如果取消為nil,則index0為特殊,以此往后類推,以第一個有效按鈕為0開始累加 //取消有的話默認為0 ***注意2*** destructiveButtonTitle iOS8以前,alert設(shè)置無效,因為不支持 iOS8以后,alert設(shè)置有效 */ + (void) showAlertWith:(UIViewController *)viewController title:(NSString *)title message:(NSString *)message callbackBlock:(CallBackBlock)block cancelButtonTitle:(NSString *)cancelBtnTitle destructiveButtonTitle:(NSString *)destructiveBtn otherButtonTitles:(NSString *)otherButtonTitles, ...NS_REQUIRES_NIL_TERMINATION;具體調(diào)用實例(默認系統(tǒng)是ios8以后的):
[JXTAlertTools showAlertWith:self title:EmptyTitle message:_titleArray[indexPath.row] callbackBlock:^(NSInteger btnIndex) {if (btnIndex == 0) {NSLog(@"取消"); } if (btnIndex == 1) {//注意ios8以前,沒有這個鍵 NSLog(@"特殊"); } if (btnIndex == 2) { NSLog(@"其他"); } } cancelButtonTitle:@"取消" destructiveButtonTitle:@"特殊" otherButtonTitles:@"其他", nil];沒有按鈕時:
//沒有按鈕時,默認自動消失[JXTAlertTools showAlertWith:self title:EmptyTitle message:_titleArray[indexPath.row] callbackBlock:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil, nil];彈窗自動消失的持續(xù)時間由宏控制,可自行修改(詳見JXTAlertTools.h):
/*** 彈框顯示的時間,默認1秒*/2.多按鈕數(shù)組模式排布alert 兼容適配alertView和alertController
/*** 多按鈕列表數(shù)組排布alert初始化 兼容適配** @param viewController 當(dāng)前視圖,alertController模態(tài)彈出的指針* @param title 標題* @param message 詳細信息* @param block 用于執(zhí)行方法的回調(diào)block * @param cancelBtnTitle 取消按鈕 * @param otherBtnTitleArray 其他按鈕的標題數(shù)組 * @param otherBtnStyleArray 按鈕樣式分布數(shù)組(普通/特殊),alertView默認為普通樣式 ***注意*** UIAlertActionStyleCancel/JXTAlertActionStyleCancel最多只能有一個,否則崩潰 Log: 'UIAlertController can only have one action with a style of UIAlertActionStyleCancel' */ + (void)showArrayAlertWith:(UIViewController *)viewController title:(NSString *)title message:(NSString *)message callbackBlock:(CallBackBlock)block cancelButtonTitle:(NSString *)cancelBtnTitle otherButtonTitleArray:(NSArray *)otherBtnTitleArray otherButtonStyleArray:(NSArray *)otherBtnStyleArray;此方法是為了彌補前面那個方法初始化時,alert的按鈕樣式排布相對固定的局限,當(dāng)然,這種排布只在iOS8之后有效。
具體調(diào)用實例(默認系統(tǒng)是ios8以后的):
NSArray * titles = @[@"確定1", @"特殊1", @"確定2", @"特殊2"]; NSArray * styles = @[ [NSNumber numberWithInteger:JXTAlertActionStyleDefault], [NSNumber numberWithInteger:JXTAlertActionStyleDestructive], [NSNumber numberWithInteger:JXTAlertActionStyleDefault], [NSNumber numberWithInteger:JXTAlertActionStyleDestructive] ]; [JXTAlertTools showArrayAlertWith:self title:EmptyTitle message:_titleArray[indexPath.row] callbackBlock:^(NSInteger btnIndex) { if (btnIndex == 0) { NSLog(@"取消"); } else NSLog(@"%@", titles[btnIndex - 1]); } cancelButtonTitle:@"取消" otherButtonTitleArray:titles otherButtonStyleArray:styles];上面要注意按鈕的樣式是枚舉值,添加數(shù)組時要注意轉(zhuǎn)化為對象,這里用了NSNumber,因為方法實現(xiàn)中也是按照NSNumber解析的:
NSNumber * styleNum = otherBtnStyleArray[i];UIAlertActionStyle actionStyle = styleNum.integerValue;UIAlertAction *otherAction = [UIAlertAction actionWithTitle:otherBtnTitleArray[i] style:actionStyle handler:^(UIAlertAction *action) { block(count); }]; [alertController addAction:otherAction];樣式枚舉定義:
typedef enum {JXTAlertActionStyleDefault = 0,JXTAlertActionStyleCancel,JXTAlertActionStyleDestructive}JXTAlertActionStyle;這里之所以不用系統(tǒng)提供的:
typedef NS_ENUM(NSInteger, UIAlertActionStyle) {UIAlertActionStyleDefault = 0,UIAlertActionStyleCancel, UIAlertActionStyleDestructive } NS_ENUM_AVAILABLE_IOS(8_0);是因為為了系統(tǒng)版本適配,系統(tǒng)的樣式枚舉是iOS8之后才提供的,如果直接使用,系統(tǒng)版本一旦低于iOS8,此時使用可能導(dǎo)致程序崩潰。
沒有按鈕時,情況同上:
[JXTAlertTools showArrayAlertWith:self title:EmptyTitle message:_titleArray[indexPath.row] callbackBlock:nil cancelButtonTitle:nil otherButtonTitleArray:nil otherButtonStyleArray:nil];關(guān)于actionSheet的API,基本同上,也提供了兩個相應(yīng)的方法,同樣是兼容適配的。
關(guān)于方法的具體實現(xiàn),在此不再贅述,有興趣的可以參考代碼,有什么問題歡迎討論。
3.兩種簡易提示窗
這兩種建議的提示窗,是基于上述方法的簡化,適用于較為簡單的提示場景。
-
1.單按鈕或無按鈕alert提示
[JXTAlertTools showTipAlertViewWith:self title:EmptyTitle message:_titleArray[indexPath.row] buttonTitle:@"確認" buttonStyle:JXTAlertActionStyleDefault]; -
2.窗口底部簡易actionSheet,無按鈕
[JXTAlertTools showBottomTipViewWith:self title:_titleArray[indexPath.row] message:_titleArray[indexPath.row]];
4.兩個特殊用途的方法
- 1.判斷當(dāng)前窗口是否有alert/actionSheet顯示 + (BOOL)isAlertShowNow; 這個的用途具體看需求,可以用來去重顯示,尤其是在alertView的情況下,有時可能連續(xù)多次彈出同一alertView,例如觀察者回調(diào),系統(tǒng)貌似沒有做去重處理,筆者就遇到過監(jiān)聽回調(diào)導(dǎo)致的alert重復(fù)顯示。但是如果是alertController,就不會發(fā)生了,控制臺可能會直接給出警告的,因為是試圖在一個已經(jīng)銷毀的vc上(第一次彈出的alertController消失時)第二次連續(xù)推出視圖,這是做不到的。
做去重顯示判定時,此方法慎用,因為未做彈窗區(qū)分,同時的彈窗有可能是因為重復(fù)顯示,也可能是不同警告類型的提示窗,去重的話就可能導(dǎo)致第二個不同的提示窗被過濾掉。
用法示例:
NSLog(@"顯示alert:%@", [JXTAlertTools isAlertShowNow] ? @"是" : @"否");if (![JXTAlertTools isAlertShowNow]) {//檢測彈窗,控制alertView的去重顯示[JXTAlertTools showTipAlertViewWith:self title:EmptyTitle message:_titleArray[indexPath.row] buttonTitle:nil buttonStyle:JXTAlertActionStyleDefault]; } NSLog(@"顯示alert:%@", [JXTAlertTools isAlertShowNow] ? @"是" : @"否");控制臺輸出:
可能用方法有問題,但我是臨時這個解決的。。。
- 2.查找當(dāng)前活動窗口 + (UIViewController *)activityViewController;
這個方法源于網(wǎng)絡(luò),實際使用可行,主要是用來確定alertController的,也就是上面那個方法有用到此方法(已封裝),當(dāng)然這個方法不局限于只確定alertController。而且,alertView的檢測和alertController的檢測不是同一個方法,畢竟一個是view,一個是vc。
5.封裝時遇到的一個小問題
當(dāng)且僅當(dāng)模擬器使用6p或者6sp時,alert有至多2個按鈕,至少1個按鈕,alert的message中使用“\n”時,分為3行,第一行無所謂,第2行字符小于38字符或者第3行字符小于76時(\n算一個字符,數(shù)字可能記錯了。。。),控制臺直接給了下面的警告,警告的達成條件較為苛刻,2、3任意一行多于臨界值都不行,但的確是偶然,同樣的字符數(shù),沒有“\n”就沒事,多于這幾個臨界值也沒事,唯獨不能少。。。:
最簡單的一個messge實例:@“1\n2\n3”
警告:
2016-01-28 10:13:47.714 JXTAlertTools[2379:60409] the behavior of the UICollectionViewFlowLayout is not defined because:
2016-01-28 10:13:47.715 JXTAlertTools[2379:60409] the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
2016-01-28 10:13:47.715 JXTAlertTools[2379:60409] The relevant UICollectionViewFlowLayout instance is <_UIAlertControllerCollectionViewFlowLayout: 0x7fc21ac7ed10>, and it is attached to <UICollectionView: 0x7fc21c877a00; frame = (0 94.6667; 270 44); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7fc21ac1b5d0>; layer = <CALayer: 0x7fc21ac1c470>; contentOffset: {0, 0}; contentSize: {0, 0}> collection view layout: <_UIAlertControllerCollectionViewFlowLayout: 0x7fc21ac7ed10>.
2016-01-28 10:13:47.715 JXTAlertTools[2379:60409] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.
不是無聊,只是偶然碰到這個情況,當(dāng)時還排查了半天,最后才發(fā)現(xiàn)是這個問題,這也是很容易遇到的問題,無論是alertView還是alertController,都會出現(xiàn)。
復(fù)制代碼:
UIAlertView * al = [[UIAlertView alloc] initWithTitle:@"title" message:@"1\n2\n2" delegate:self cancelButtonTitle:@"ok" otherButtonTitles:nil, nil]; [al show];或者:
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"title" message:@"1\n2\n2" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction * act =[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { NSLog(@"輸出"); }]; [alert addAction:act]; [self presentViewController:alert animated:YES completion:nil];用6p或者6sp運行,就會出現(xiàn)上述警告,原因不明(系統(tǒng)bug?)。。。其他模擬器都沒事。這里提出來只是提醒注意規(guī)避吧。
而且分析上述警告也很有意思,大致是說UICollectionView的布局有問題,這是不是可以說明系統(tǒng)的alertView或者alertController都是利用UICollectionView進行封裝的呢?
上述臨界情況的樣式:
1.不會出現(xiàn)的:
2.會出現(xiàn)的,僅僅是少了一個字符:
參考文章:
1.iOS 引用當(dāng)前顯示的UIAlertView
2.IOS -獲取當(dāng)前視圖的Controller
3.UIWindowLevel詳解
·轉(zhuǎn)載請聲明出處·
轉(zhuǎn)載于:https://www.cnblogs.com/Free-Thinker/p/7080879.html
總結(jié)
以上是生活随笔為你收集整理的iOS (封装)一句话调用系统的alertView和alertController的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么 时候用转义字符
- 下一篇: java信息管理系统总结_java实现科