iOS:簡(jiǎn)單使用UIAlertVIew和UIActionSheet

做iOS開發(fā)的同學(xué)想必都用過UIAlertVIew或者UIActionSheet。UIAlertVIew 可以彈出一個(gè)出現(xiàn)在屏幕中間的提示視圖仗嗦,給用戶展示信息雪标,并讓用戶自己選擇操作筷狼,UIActionSheet可以彈出一個(gè)選擇列表动看,讓用戶選擇列表中的某一項(xiàng)操作。使用UIAlertVIew和UIActionSheet非常簡(jiǎn)單躲撰,以下是一個(gè)簡(jiǎn)單的示例代碼:

//UIAlertView
- (void)someButtonClicked {//初始化AlertView  
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"AlertViewTest"  
                                               message:@"message"  
                                              delegate:self  
                                     cancelButtonTitle:@"Cancel"  
                                     otherButtonTitles:@"OtherBtn",nil]; 
[alert show]; 
}
//按鈕點(diǎn)擊事件的代理
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    NSLog(@"clickButtonAtIndex:%d",(int)buttonIndex); 
    //index為-1則是取消针贬,
}


//UIActionSheet
- (void)someButtonClicked { 
    UIActionSheet * sheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"ddd" destructiveButtonTitle:@"aaa" otherButtonTitles:@"bbb", @"ccc", @"ddd", nil]; 
    sheet.destructiveButtonIndex = 1;
    [sheet showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
     NSLog(@"result = %d", (int)buttonIndex);
}

雖然使用已經(jīng)算是比較簡(jiǎn)單了,但我覺得還是比較麻煩他們都需要設(shè)置delegate來獲得用戶選擇的結(jié)果拢蛋。這么小的界面桦他,把調(diào)用顯示和回調(diào)方法分開寫在2個(gè)方法中,使得原本簡(jiǎn)單的邏輯復(fù)雜了。雖然也不會(huì)復(fù)雜到哪兒去快压,但是每次調(diào)用他們就需要另外寫一個(gè)delegate回調(diào)方法圆仔,覺得還是比較麻煩。
于是便產(chǎn)生了蔫劣,分別給它們寫一個(gè)category 用來對(duì)原生的ui再做一層簡(jiǎn)單地封裝坪郭。(一些復(fù)雜的暫不考慮)然后用block來做回調(diào),這樣子脉幢,一塊簡(jiǎn)單地東西就不用分開在兩個(gè)地方了(才不要拆散它們)歪沃。
我們先簡(jiǎn)單地分析 UIAlertVIew 和 UIActionSheet,其實(shí)他們需要的東西嫌松,并不多沪曙,只是按鈕的事件和對(duì)應(yīng)的action,UIAlertVIew還多了一個(gè)Title和message萎羔,但這些在初始化里面就已經(jīng)初始化好了液走。造成他們分離的主要原因還是action和init分離了。所以要完成這個(gè)不讓他們分離的目的贾陷,實(shí)現(xiàn)這個(gè)category 首先我們需要一個(gè) button的模型來封裝 button的title 和 對(duì)應(yīng)的事件缘眶,事件用block來代替代理(這樣就可以讓他們?cè)谝黄鹆耍?br> 于是我順手在github上搜索了一下,發(fā)現(xiàn)了這個(gè)
https://github.com/jivadevoe/UIAlertView-Blocks
哈哈哈哈髓废,全文終~~
好吧巷懈,不鬧,既然那讓我們來看一下它的實(shí)現(xiàn)慌洪,這個(gè)擴(kuò)展很簡(jiǎn)單砸喻,就是六個(gè)文件,對(duì)應(yīng)RIButtonItem.h蒋譬、RIButtonItem.m UIActionSheet+Blocks.h、UIActionSheet+Blocks.m UIAlertView+Blocks.h愉适、UIAlertView+Blocks.m

RIButtonItem.h

@interface RIButtonItem : NSObject
{
    NSString *label;
    void (^action)();
}
@property (strong, nonatomic) NSString *label;
@property (copy, nonatomic) void (^action)();
+(id)item;
+(id)itemWithLabel:(NSString *)inLabel;
@end

ok犯助,我們很容易看到,這里面的內(nèi)容和我們前面想的實(shí)現(xiàn)幾乎一樣维咸,用一個(gè)label來存儲(chǔ)標(biāo)題剂买,(^action)()來記錄點(diǎn)擊按鈕的事件。
RIButtonItem.m代碼很簡(jiǎn)單癌蓖,這里不貼了瞬哼。

剩下的兩個(gè)UIAlertView+Blocks UIActionSheet+Blocks 因?yàn)閷?shí)現(xiàn)類似我們來看一個(gè)的實(shí)現(xiàn)

UIAlertView+Blocks.h

#import <UIKit/UIKit.h>

#import "RIButtonItem.h"`

@interface UIAlertView (Blocks) <UIActionSheetDelegate>  

-(id)initWithTitle:(NSString *)inTitle message:(NSString *)inMessage cancelButtonItem:(RIButtonItem *)inCancelButtonItem otherButtonItems:(RIButtonItem *)inOtherButtonItems, ... NS_REQUIRES_NIL_TERMINATION;   //1

- (NSInteger)addButtonItem:(RIButtonItem *)item;   //2
@end

1.我們可以看到初始化方法幾乎和UIAlertView 初始化一樣,只是用RIButtonItem來代替原來的按鈕標(biāo)題租副,用RIButtonItem把a(bǔ)ction帶上就省略了原來的delegate方法
2.這個(gè)方法則對(duì)應(yīng)了 addButtonWithTitle 方法

重點(diǎn)來了坐慰,來看UIAlertView+Blocks.m的實(shí)現(xiàn)

#import "UIAlertView+Blocks.h"
#import <objc/runtime.h>

static NSString *RI_BUTTON_ASS_KEY = @"com.random-ideas.BUTTONS";

@implementation UIAlertView (Blocks)

-(id)initWithTitle:(NSString *)inTitle message:(NSString *)inMessage cancelButtonItem:(RIButtonItem *)inCancelButtonItem otherButtonItems:(RIButtonItem *)inOtherButtonItems, ... 
{
    if((self = [self initWithTitle:inTitle message:inMessage delegate:self cancelButtonTitle:inCancelButtonItem.label otherButtonTitles:nil]))
    {
        NSMutableArray *buttonsArray = [NSMutableArray array];
        
        RIButtonItem *eachItem;
        va_list argumentList;       //1      
        if (inOtherButtonItems)                     
        {                                  
            [buttonsArray addObject: inOtherButtonItems];   
            va_start(argumentList, inOtherButtonItems);       //2
            while((eachItem = va_arg(argumentList, RIButtonItem *)))       //3
            {
                [buttonsArray addObject: eachItem];
            }
            va_end(argumentList);      //4
        }    
        
        for(RIButtonItem *item in buttonsArray)
        {
            [self addButtonWithTitle:item.label];
        }
        
        if(inCancelButtonItem)
            [buttonsArray insertObject:inCancelButtonItem atIndex:0];
        
        objc_setAssociatedObject(self, (const void *)RI_BUTTON_ASS_KEY, buttonsArray, OBJC_ASSOCIATION_RETAIN_NONATOMIC);   //5
        
        [self setDelegate:self];
    }
    return self;
}

- (NSInteger)addButtonItem:(RIButtonItem *)item
{ 
    NSMutableArray *buttonsArray = objc_getAssociatedObject(self, (const void *)RI_BUTTON_ASS_KEY);
 
 NSInteger buttonIndex = [self addButtonWithTitle:item.label];
 [buttonsArray addObject:item];
 
 return buttonIndex;
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    // If the button index is -1 it means we were dismissed with no selection
    if (buttonIndex >= 0)
    {
        NSArray *buttonsArray = objc_getAssociatedObject(self, (const void *)RI_BUTTON_ASS_KEY);     //6
        RIButtonItem *item = [buttonsArray objectAtIndex:buttonIndex];
        if(item.action)
            item.action();
    }
    
    objc_setAssociatedObject(self, (const void *)RI_BUTTON_ASS_KEY, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);     //7
}

@end
  1. va_list 是ios實(shí)現(xiàn)傳遞不定長(zhǎng)的多個(gè)參數(shù)的方法時(shí)所使用的
  2. 然后用va_start初始化剛定義的va_list變量
  3. 然后用va_arg返回可變的參數(shù),va_arg的第二個(gè)參數(shù)是你要返回的參數(shù)的類型.如果函數(shù)有多個(gè)可變參數(shù)的用僧,依次調(diào)用va_arg獲取各個(gè)參數(shù)结胀;
    下面就是如果還有其他的buttonItem就把它加到buttonsArray
  4. 最后用va_end宏結(jié)束可變參數(shù)的獲取赞咙。
  5. 因?yàn)樵赾ategory里面不能添加成員變量,所以用objc_setAssociatedObject和objc_getAssociatedObject來變相的添加buttonArray方便下面delegate的時(shí)候取出buttonArray里的action
  6. 取出buttonArray糟港,使用block來實(shí)現(xiàn)回調(diào)方法攀操。
  7. set nil;

代碼分析差不多,還學(xué)習(xí)了va_list 以后也能方便的使用這兩個(gè)彈出框了秸抚。

上一個(gè)使用例子


code.png

敲下一塊代碼就出現(xiàn)了下面的彈框速和,很方便是不是。

alertView.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剥汤,一起剝皮案震驚了整個(gè)濱河市颠放,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秀姐,老刑警劉巖慈迈,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異省有,居然都是意外死亡痒留,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蠢沿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伸头,“玉大人,你說我怎么就攤上這事舷蟀⌒袅祝” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵野宜,是天一觀的道長(zhǎng)扫步。 經(jīng)常有香客問我,道長(zhǎng)匈子,這世上最難降的妖魔是什么河胎? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮虎敦,結(jié)果婚禮上游岳,老公的妹妹穿的比我還像新娘。我一直安慰自己其徙,他們只是感情好胚迫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著唾那,像睡著了一般访锻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天朗若,我揣著相機(jī)與錄音恼五,去河邊找鬼。 笑死哭懈,一個(gè)胖子當(dāng)著我的面吹牛灾馒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播遣总,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼睬罗,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了旭斥?” 一聲冷哼從身側(cè)響起容达,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎垂券,沒想到半個(gè)月后花盐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菇爪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年算芯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凳宙。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡熙揍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氏涩,到底是詐尸還是另有隱情届囚,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布是尖,位于F島的核電站意系,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏饺汹。R本人自食惡果不足惜昔字,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望首繁。 院中可真熱鬧,春花似錦陨囊、人聲如沸弦疮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胁塞。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間啸罢,已是汗流浹背编检。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扰才,地道東北人允懂。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像衩匣,于是被迫代替她去往敵國(guó)和親蕾总。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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