iOS:簡單使用UIAlertVIew和UIActionSheet


做iOS開發的同學想必都用過UIAlertVIew或者UIActionSheet。UIAlertVIew 可以彈出一個出現在屏幕中間的提示視圖,給用戶展示信息,並讓用戶自己選擇操作,UIActionSheet可以彈出一個選擇列表,讓用戶選擇列表中的某一項操作。使用UIAlertVIew和UIActionSheet非常簡單,以下是一個簡單的示例代碼:

//UIAlertView - (void)someButtonClicked {//初始化AlertView UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"AlertViewTest" message:@"message" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OtherBtn",nil]; [alert show]; } //按鈕點擊事件的代理 - (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); }

雖然使用已經算是比較簡單了,但我覺得還是比較麻煩他們都需要設置delegate來獲得用戶選擇的結果。這么小的界面,把調用顯示和回調方法分開寫在2個方法中,使得原本簡單的邏輯復雜了。雖然也不會復雜到哪兒去,但是每次調用他們就需要另外寫一個delegate回調方法,覺得還是比較麻煩。
於是便產生了,分別給它們寫一個category 用來對原生的ui再做一層簡單地封裝。(一些復雜的暫不考慮)然后用block來做回調,這樣子,一塊簡單地東西就不用分開在兩個地方了(才不要拆散它們)。
我們先簡單地分析 UIAlertVIew 和 UIActionSheet,其實他們需要的東西,並不多,只是按鈕的事件和對應的action,UIAlertVIew還多了一個Title和message,但這些在初始化里面就已經初始化好了。造成他們分離的主要原因還是action和init分離了。所以要完成這個不讓他們分離的目的,實現這個category 首先我們需要一個 button的模型來封裝 button的title 和 對應的事件,事件用block來代替代理(這樣就可以讓他們在一起了)。
於是我順手在github上搜索了一下,發現了這個
https://github.com/jivadevoe/UIAlertView-Blocks
哈哈哈哈,全文終~~
好吧,不鬧,既然那讓我們來看一下它的實現,這個擴展很簡單,就是六個文件,對應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,我們很容易看到,這里面的內容和我們前面想的實現幾乎一樣,用一個label來存儲標題,(^action)()來記錄點擊按鈕的事件。
RIButtonItem.m代碼很簡單,這里不貼了。

剩下的兩個UIAlertView+Blocks UIActionSheet+Blocks 因為實現類似我們來看一個的實現

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來代替原來的按鈕標題,用RIButtonItem把action帶上就省略了原來的delegate方法
2.這個方法則對應了 addButtonWithTitle 方法

重點來了,來看UIAlertView+Blocks.m的實現

#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實現傳遞不定長的多個參數的方法時所使用的
  2. 然后用va_start初始化剛定義的va_list變量
  3. 然后用va_arg返回可變的參數,va_arg的第二個參數是你要返回的參數的類型.如果函數有多個可變參數的,依次調用va_arg獲取各個參數;
    下面就是如果還有其他的buttonItem就把它加到buttonsArray
  4. 最后用va_end宏結束可變參數的獲取。
  5. 因為在category里面不能添加成員變量,所以用objc_setAssociatedObject和objc_getAssociatedObject來變相的添加buttonArray方便下面delegate的時候取出buttonArray里的action
  6. 取出buttonArray,使用block來實現回調方法。
  7. set nil;

代碼分析差不多,還學習了va_list 以后也能方便的使用這兩個彈出框了。

上一個使用例子


code.png

敲下一塊代碼就出現了下面的彈框,很方便是不是。


alertView.png


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM