iOS 更加優(yōu)雅便捷的UIAlertView/UIAlertController封裝使用

現(xiàn)已支持CocoaPods

前言:

之前做過(guò)一套關(guān)于UIAlertView/UIAlertController的混合封裝(舊版封裝鏈接:iOS (封裝)一句話調(diào)用系統(tǒng)的alertView和alertController
那個(gè)是將alertView和alertController做了版本適配封裝在一起的揍愁,提供了變參和數(shù)組兩種方式蝴悉,不過(guò)現(xiàn)在看來(lái),雖然是“一句話”調(diào)用咆贬,但并不是很優(yōu)雅的方式。

這次辟拷,改變了方案撞羽,將UIAlertView和UIAlertController分開(kāi)進(jìn)行了處理,整體代碼也輕量了很多衫冻。
新版的代碼及Demo見(jiàn)GitHub:

JXTAlertManager

  • 基于UIAlertView封裝的JXTAlertView诀紊,這個(gè)是將之前寫(xiě)Demo時(shí)搞的一套快捷使用alertView的工具抽離整理出來(lái)的,并提供了C函數(shù)直接調(diào)用隅俘,像這樣:
    jxt_showAlertTitle(@"簡(jiǎn)易調(diào)試使用alert邻奠,單按鈕,標(biāo)題默認(rèn)為“確定”");
    就可以直接顯示出一個(gè)alertView为居。
  • 基于UIAlertController封裝的JXTAlertController碌宴,支持iOS8及以上。調(diào)用方式為UIViewController的擴(kuò)展分類方法蒙畴,支持使用鏈?zhǔn)秸Z(yǔ)法的方式配置alert的按鈕及樣式唧喉,相對(duì)于變參或者數(shù)組,更加簡(jiǎn)潔忍抽。
JXTAlertManager大體結(jié)構(gòu)

1. JXTAlertView 便捷調(diào)試工具

之所以叫做快捷調(diào)試工具八孝,就是因?yàn)檫@套代碼是之前寫(xiě)Demo時(shí)搞出來(lái)的。所以鸠项,如果不是要適配iOS7及以下版本的話干跛,這套代碼還是建議只用在平時(shí)Demo測(cè)試。也因此祟绊,并沒(méi)有針對(duì)UIActionSheet再進(jìn)行封裝楼入,說(shuō)白了是因?yàn)閼小?br> 平時(shí)寫(xiě)一些Demo代碼時(shí),總會(huì)用到alert牧抽、toast嘉熊、HUD這些工具,如果沒(méi)有一套簡(jiǎn)便的工具,會(huì)麻煩很多,所以便從輕量便捷角度出發(fā)阵漏,基于UIAlertView炫乓,封裝實(shí)現(xiàn)了alert吴藻、toast、HUD這些常用工具。

JXTAlertView大致效果演示

1.1.快捷使用alertView

如果只是簡(jiǎn)單的一個(gè)提示,可以這樣使用(這里只是一個(gè)示例衫画,詳細(xì)用法見(jiàn)源碼):
jxt_showAlertTitle(@"簡(jiǎn)易調(diào)試使用alert,單按鈕瓮栗,標(biāo)題默認(rèn)為“確定”");
其實(shí)現(xiàn)是基于:

[JXTAlertView showAlertViewWithTitle:title 
                             message:message 
                   cancelButtonTitle:cancelButtonTitle 
                    otherButtonTitle:otherButtonTitle
                   cancelButtonBlock:cancelBlock 
                    otherButtonBlock:otherBlock];

這是常用的兩個(gè)以內(nèi)的按鈕的alertView削罩,也可以這樣使用:

jxt_showAlertTwoButton(@"title", @"message", @"cancel", ^(NSInteger buttonIndex) {
    NSLog(@"cancel");
}, @"other", ^(NSInteger buttonIndex) {
    NSLog(@"other");
});

針對(duì)于復(fù)雜的多按鈕的alertView瞄勾,還是使用變參方式,按鈕響應(yīng)弥激,根據(jù)添加的按鈕標(biāo)題的index號(hào)依序區(qū)分:

[JXTAlertView showAlertViewWithTitle:@"title"
                             message:@"message"
                   cancelButtonTitle:@"cancel"
                    buttonIndexBlock:^(NSInteger buttonIndex) {
    if (buttonIndex == 0) {
        NSLog(@"cancel");
    }
    else if (buttonIndex == 1) {
        NSLog(@"按鈕1");
    }
    else if (buttonIndex == 2) {
        NSLog(@"按鈕2");
    }
    else if (buttonIndex == 3) {
        NSLog(@"按鈕3");
    }
    else if (buttonIndex == 4) {
        NSLog(@"按鈕4");
    }
    else if (buttonIndex == 5) {
        NSLog(@"按鈕5");
    }
} otherButtonTitles:@"按鈕1", @"按鈕2", @"按鈕3", @"按鈕4", @"按鈕5", nil];

1.2.簡(jiǎn)單的toast

這里的toast提示丰榴,有別于傳統(tǒng)意義上的toast,因?yàn)槠涫腔赼lertView實(shí)現(xiàn)的秆撮,是一個(gè)沒(méi)有按鈕的alertView』豢觯可自定義展示延時(shí)時(shí)間职辨,支持關(guān)閉回調(diào)的配置。

[JXTAlertView showToastViewWithTitle:@"title"
                             message:@"message"
                            duration:2
                   dismissCompletion:^(NSInteger buttonIndex) {
    NSLog(@"關(guān)閉");
}];

1.3.三種HUD的實(shí)現(xiàn)

這里的HUD區(qū)別于toast之處在于戈二,其關(guān)閉時(shí)機(jī)可控舒裤,并不是單純的一個(gè)延時(shí)展示。
三種HUD是指單純的文字型觉吭、帶風(fēng)火輪(菊花)的加載窗腾供、帶進(jìn)度條的加載窗。
后兩者用KVC的方式訪問(wèn)了alertView的私有屬性accessoryView實(shí)現(xiàn)鲜滩,這樣做可能沒(méi)有太大問(wèn)題伴鳖,不過(guò)還是不建議線上開(kāi)發(fā)使用,而且利用這種方式訪問(wèn)私有屬性本來(lái)就是不太安全的徙硅,一旦key(私有屬性名)改變了榜聂,不做容錯(cuò)處理,會(huì)崩潰嗓蘑,源碼實(shí)現(xiàn)中做了一定的容錯(cuò)须肆,但是,一旦對(duì)應(yīng)key變化桩皿,也就導(dǎo)致對(duì)應(yīng)功能失效了豌汇。

  • 示例代碼(C函數(shù)方式):
jxt_showLoadingHUDTitleMessage(@"title", @"message");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    jxt_dismissHUD();
});

HUD還有對(duì)應(yīng)的簡(jiǎn)易的顯示加載成功失敗狀態(tài)的方法,以及刷新進(jìn)度條進(jìn)度值的方法泄隔,詳情見(jiàn)Demo拒贱。

2. JXTAlertController(iOS8)(鏈?zhǔn)秸Z(yǔ)法的“隱患”)

JXTAlertController是基于系統(tǒng)的UIAlertController封裝的,因此也只能支持iOS8及以上系統(tǒng)版本佛嬉。
雖然源碼中的JXTAlertManagerHeader.h做了一個(gè)版本適配柜思,但是,其意義更多在于提示巷燥,很可能因此出錯(cuò)赡盘,所以,如果要適配iOS7缰揪,對(duì)應(yīng)方法還是需要自行適配陨享。
下面都以alert舉例葱淳,actionSheet同理。

JXTAlertController大致效果演示

2.1.結(jié)構(gòu)說(shuō)明

/**
 JXTAlertController: show-alert(iOS8)

 @param title             title
 @param message           message
 @param appearanceProcess alert配置過(guò)程
 @param actionBlock       alert點(diǎn)擊響應(yīng)回調(diào)
 */
- (void)jxt_showAlertWithTitle:(nullable NSString *)title
                       message:(nullable NSString *)message
             appearanceProcess:(JXTAlertAppearanceProcess)appearanceProcess
                  actionsBlock:(nullable JXTAlertActionBlock)actionBlock NS_AVAILABLE_IOS(8_0);

上述方法是針對(duì)UIViewController做的分類擴(kuò)展抛姑,詳見(jiàn)源碼赞厕。
也就是在某個(gè)VC中使用時(shí),可直接用self指針調(diào)用定硝。
JXTAlertAppearanceProcess是配置塊皿桑,JXTAlertActionBlock是按鈕響應(yīng)回調(diào)塊。

2.2.鏈?zhǔn)秸Z(yǔ)法添加按鈕

[self jxt_showActionSheetWithTitle:@"title"
                           message:@"message"
                 appearanceProcess:^(JXTAlertController * _Nonnull alertMaker) {
    alertMaker.
    addActionCancelTitle(@"cancel").
    addActionDestructiveTitle(@"按鈕1").
    addActionDefaultTitle(@"按鈕2").
    addActionDefaultTitle(@"按鈕3").
    addActionDestructiveTitle(@"按鈕4");
} actionsBlock:^(NSInteger buttonIndex, UIAlertAction * _Nonnull action, JXTAlertController * _Nonnull alertSelf) {
    
    if ([action.title isEqualToString:@"cancel"]) {
        NSLog(@"cancel");
    }
    else if ([action.title isEqualToString:@"按鈕1"]) {
        NSLog(@"按鈕1");
    }
    else if ([action.title isEqualToString:@"按鈕2"]) {
        NSLog(@"按鈕2");
    }
    else if ([action.title isEqualToString:@"按鈕3"]) {
        NSLog(@"按鈕3");
    }
    else if ([action.title isEqualToString:@"按鈕4"]) {
        NSLog(@"按鈕4");
    }
}];

appearanceProcess配置塊中蔬啡,alertMaker是當(dāng)前alertController對(duì)象诲侮,addActionCancelTitle(@"cancel")是添加一個(gè)按鈕,其等效于:

[alertController addAction:[UIAlertAction actionWithTitle:@"cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
    
}]];

這里引入了簡(jiǎn)單的鏈?zhǔn)秸Z(yǔ)法箱蟆,可以連續(xù)添加系統(tǒng)支持的三類action按鈕沟绪,當(dāng)然UIAlertActionStyleCancel這個(gè)樣式的action只能添加一次。這樣可以大大簡(jiǎn)化代碼空猜。

actionsBlock是action按鈕響應(yīng)回調(diào)绽慈,可以根據(jù)index區(qū)分響應(yīng),index根據(jù)執(zhí)行add的語(yǔ)法鏈從0依序增加辈毯,cancel類型的action布局位置是固定的坝疼,和添加順序無(wú)關(guān),但其index與添加順序有關(guān)谆沃。
對(duì)于復(fù)雜或者特殊的alertController裙士,也可以根據(jù)action.title或者action區(qū)分響應(yīng)。

2.3.鏈?zhǔn)秸Z(yǔ)法的“隱患”

用過(guò)Masonry這個(gè)庫(kù)的管毙,應(yīng)該都對(duì)鏈?zhǔn)秸Z(yǔ)法不會(huì)太陌生腿椎。鏈?zhǔn)秸Z(yǔ)法可以使得代碼簡(jiǎn)化且邏輯清晰化。但是夭咬,其也有一定的“隱患”存在啃炸。
Masonry應(yīng)該是用的最多的一個(gè)自動(dòng)布局的三方庫(kù),類似的還有SDAutoLayout(這里只是舉例卓舵,同樣的三方還有很多南用,這個(gè)應(yīng)該是除了Masonry外,用的相對(duì)多一些的一個(gè))這樣的掏湾,同樣的鏈?zhǔn)秸Z(yǔ)法裹虫,后者似乎更加簡(jiǎn)潔優(yōu)雅。那為什么大名鼎鼎的Masonry不這么干呢融击?我想是因?yàn)椤鞍踩薄?/p>

SDAutoLayout的Demo做一個(gè)實(shí)驗(yàn):

view為nil導(dǎo)致的崩潰

這里把view0置為nil筑公,之后運(yùn)行,程序直接崩潰了尊浪。匣屡。封救。這類似于執(zhí)行一個(gè)未賦值的空block捣作。
有人可能會(huì)認(rèn)為這樣的實(shí)驗(yàn)沒(méi)有意義誉结,為nil了干嘛還要布局呢券躁?其實(shí)這是筆者前陣子在封裝一個(gè)鏈?zhǔn)綆?kù)時(shí)遇到的問(wèn)題:實(shí)際應(yīng)用開(kāi)發(fā)中惩坑,情況要復(fù)雜很多以舒,有些view是動(dòng)態(tài)添加的,甚至是根據(jù)接口數(shù)據(jù)動(dòng)態(tài)創(chuàng)建的搪泳,如果在處理這類代碼邏輯中稍有不慎岸军,就會(huì)造成上述問(wèn)題,給不存在的view進(jìn)行布局瓦侮,直接導(dǎo)致程序崩潰艰赞。。肚吏。
其實(shí)這也是代碼書(shū)寫(xiě)規(guī)范的問(wèn)題方妖,針對(duì)這類動(dòng)態(tài)view,在處理時(shí)罚攀,本就應(yīng)該添加if條件判斷的党觅,不過(guò)有時(shí)容易忽視,或者他人接手相關(guān)代碼時(shí)斋泄,也容易忽略杯瞻。如果用Masonry的塊配置布局,就不會(huì)發(fā)生這類問(wèn)題炫掐,因?yàn)檫@種情況魁莉,對(duì)于Masonry那種寫(xiě)法,就是一個(gè)空指針執(zhí)行一個(gè)方法募胃,其結(jié)果就是不執(zhí)行旗唁,而像SDAutoLayout這類的,不作判空處理痹束,就會(huì)導(dǎo)致程序崩潰检疫。這里尤其要注意。

2.4.其他配置

針對(duì)alert上的輸入框祷嘶,保持系統(tǒng)的添加方式电谣,示例如下:

[self jxt_showAlertWithTitle:@"title"
                     message:@"message"
           appearanceProcess:^(JXTAlertController * _Nonnull alertMaker) {
    alertMaker.
    addActionDestructiveTitle(@"獲取輸入框1").
    addActionDestructiveTitle(@"獲取輸入框2");

    [alertMaker setAlertDidShown:^{
        [self logMsg:@"alertDidShown"];//不用擔(dān)心循環(huán)引用
    }];
    alertMaker.alertDidDismiss = ^{
        [self logMsg:@"alertDidDismiss"];
    };
    
    [alertMaker addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = @"輸入框1-請(qǐng)輸入";
    }];
    [alertMaker addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
        textField.placeholder = @"輸入框2-請(qǐng)輸入";
    }];
} actionsBlock:^(NSInteger buttonIndex, UIAlertAction * _Nonnull action, JXTAlertController * _Nonnull alertSelf) {
    if (buttonIndex == 0) {
        UITextField *textField = alertSelf.textFields.firstObject;
        [self logMsg:textField.text];//不用擔(dān)心循環(huán)引用
    }
    else if (buttonIndex == 1) {
        UITextField *textField = alertSelf.textFields.lastObject;
        [self logMsg:textField.text];
    }
}];

對(duì)于alert展示和關(guān)閉的回調(diào)秽梅,同樣支持以block的方式配置。
如果appearanceProcess塊不進(jìn)行任何配置操作剿牺,即無(wú)按鈕的alert企垦,同樣默認(rèn)以toast模式處理∩估矗可通過(guò)設(shè)置toastStyleDuration屬性钞诡,配置toast展示延遲時(shí)間。

2.5.改變alertController的字體顏色

可以通過(guò)KVC的方式訪問(wèn)alertController的私有屬性湃崩,從而進(jìn)行修改對(duì)應(yīng)的字體的顏色荧降,甚至字體。
對(duì)于UIAlertAction攒读,可以用下面的方式修改字體顏色:
[alertAction setValue:[UIColor grayColor] forKey:@"titleTextColor"];

修改UIAlertAction字體顏色的效果

但是就像前面說(shuō)的朵诫,個(gè)人并不推薦這類方式,所以源碼中沒(méi)有提供相關(guān)的方法薄扁。
如果有對(duì)應(yīng)的特殊需求剪返,總體來(lái)說(shuō),還是自定義alert視圖比較靈活邓梅,網(wǎng)上相關(guān)的開(kāi)源庫(kù)也有很多可以直接使用脱盲,不必總是糾結(jié)于系統(tǒng)的實(shí)現(xiàn)方式。

最后日缨,歡迎使用JXTAlertManager钱反,如果遇到任何問(wèn)題,請(qǐng)及時(shí)聯(lián)系作者匣距。

參考文章:
1.iOS更改UIActionController彈出字體的樣式
2.UIAlertController 簡(jiǎn)單修改title以及按鈕的字體顏色
3.How to add subview inside UIAlertView for iOS 7?
4.UIAlertView addSubview in iOS7
5.iOS UIAlertView中UIActivityindicatorView風(fēng)火輪提示加載等待

·轉(zhuǎn)載請(qǐng)聲明作者面哥、出處·

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市毅待,隨后出現(xiàn)的幾起案子幢竹,更是在濱河造成了極大的恐慌,老刑警劉巖恩静,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焕毫,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡驶乾,警方通過(guò)查閱死者的電腦和手機(jī)邑飒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)级乐,“玉大人疙咸,你說(shuō)我怎么就攤上這事》缈疲” “怎么了撒轮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵乞旦,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我题山,道長(zhǎng)兰粉,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任顶瞳,我火速辦了婚禮玖姑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘慨菱。我一直安慰自己焰络,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布符喝。 她就那樣靜靜地躺著闪彼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪协饲。 梳的紋絲不亂的頭發(fā)上畏腕,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音囱稽,去河邊找鬼郊尝。 笑死二跋,一個(gè)胖子當(dāng)著我的面吹牛战惊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扎即,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼吞获,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了谚鄙?” 一聲冷哼從身側(cè)響起各拷,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闷营,沒(méi)想到半個(gè)月后烤黍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡傻盟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年速蕊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娘赴。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡规哲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诽表,到底是詐尸還是另有隱情唉锌,我是刑警寧澤隅肥,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站袄简,受9級(jí)特大地震影響腥放,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜痘番,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一捉片、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汞舱,春花似錦伍纫、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至泌神,卻和暖如春良漱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背欢际。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工母市, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人损趋。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓患久,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親浑槽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蒋失,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件桐玻、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,024評(píng)論 4 62
  • 在斯利美門口篙挽,我們相擁而別,說(shuō)著甜膩的告別話镊靴,末了铣卡,揮揮手,我背著你們往家走偏竟,烈日烤得我透不過(guò)氣來(lái)煮落,一不小心把我心...
    九娘閱讀 311評(píng)論 0 2
  • 提起“選擇”二字,對(duì)于善于選擇的人來(lái)說(shuō)只是平常小事苫耸;而對(duì)于選擇起來(lái)有頗多困難的人來(lái)說(shuō)州邢,就是大事啦。 我也不知道為何...
    木子骙骙閱讀 255評(píng)論 0 0
  • 第十六天打卡 可愛(ài)的老虎 準(zhǔn)備材料 一根鉛筆 一塊橡皮 一支黑筆 一盒彩色鉛筆 一張白紙 繪圖步驟 1.在...
    趙縵纓閱讀 1,734評(píng)論 0 1