zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    JavaScript经典效果集锦之五(转)
    消息队列函数
    ipcs查看消息队列命令
    sizeof的解析
    【转】使用Reporting Services制做可折叠的报表
    【转】Hibernate动态条件查询(Criteria Query)
    【Wonder原创】NHibernate调用存储过程
    【转】C# const和readonly的区别
    【转】人际关系经验
    winform只存在一个进程处理
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/7084823.html
Copyright © 2011-2022 走看看