zoukankan      html  css  js  c++  java
  • Objective-C Runtime之着魔的UIAlertView

    前言:

    上篇文章写的是Runtime的一个入门教程,刚哥问我那个Associated Objects加回调是啥时候用,那我就来告诉你啦!我们在使用UIAlertView的时候用的多。

    传统的UIAlertView:

    在一个类中有多个UIAlertView,不同的UIAlertView对应不同的事件,我们使用的传统方法如下:

     1 #pragma mark - action method
     2 
     3 - (IBAction)firstButtonClick:(id)sender {
     4     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
     5     alertView.tag = 1001;
     6     [alertView show];
     7 }
     8 
     9 - (IBAction)secondButtonClick:(id)sender {
    10     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
    11     alertView.tag = 1002;
    12     [alertView show];
    13 }
    14 
    15 - (IBAction)ThirdButtonClick:(id)sender {
    16     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
    17     alertView.tag = 1003;
    18     [alertView show];
    19 }
    20 
    21 #pragma mark - delegate method
    22 
    23 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    24 {
    25     if (alertView.tag == 1001) {
    26         if (buttonIndex == 1) {
    27             NSLog(@"普通alertView1001执行ok");
    28         }
    29     } else if (alertView.tag == 1002) {
    30         if (buttonIndex == 1) {
    31             NSLog(@"普通alertView1002执行ok");
    32         }
    33     } else if (alertView.tag == 1003) {
    34         if (buttonIndex == 1) {
    35             NSLog(@"普通alertView1003执行ok");
    36         }
    37     }
    38 }

    我们要给每个UIAlertView赋值一个tag值,在delegate方法中还要进行tag的判断以及buttonIndex的判断,太繁琐了。

    着魔的UIAlertView:

    下面我们使用Category和Associated Objects进行魔法修改

    创建一个UIAlertView的Category

    UIAlertView+ActionBlock.h

    1 #import <UIKit/UIKit.h>
    2 
    3 typedef void (^AlertCallBack)(UIAlertView *, NSUInteger);
    4 
    5 @interface UIAlertView (ActionBlock)<UIAlertViewDelegate>
    6 
    7 @property (nonatomic, copy) AlertCallBack callBack;
    8 
    9 @end

    UIAlertView+ActionBlock.m

     1 #if TARGET_IPHONE_SIMULATOR
     2 #import <objc/objc-runtime.h>
     3 #else
     4 #import <objc/runtime.h>
     5 #import <objc/message.h>
     6 #endif
     7 
     8 @implementation UIAlertView (ActionBlock)
     9 
    10 - (void)setCallBack:(AlertCallBack)callBack
    11 {
    12     objc_setAssociatedObject(self, @selector(callBack), callBack, OBJC_ASSOCIATION_COPY_NONATOMIC);
    13     self.delegate = self;
    14 }
    15 
    16 - (AlertCallBack)callBack
    17 {
    18     return objc_getAssociatedObject(self, @selector(callBack));
    19 }
    20 
    21 #pragma mark - delegate method
    22 
    23 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    24 {
    25     if (self.callBack) {
    26         self.callBack(alertView, buttonIndex);
    27     }
    28 }

    在主类中取消delegate,使用block属性

     1 #pragma mark - action method
     2 
     3 - (IBAction)firstButtonClick:(id)sender {
     4     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
     5     alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){
     6         if (buttonIndex == 1) {
     7             NSLog(@"魔法alertView1001执行ok");
     8         }
     9     };
    10     [alertView show];
    11 }
    12 
    13 - (IBAction)secondButtonClick:(id)sender {
    14     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
    15     alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){
    16         if (buttonIndex == 1) {
    17             NSLog(@"魔法alertView1002执行ok");
    18         }
    19     };
    20     [alertView show];
    21 }
    22 
    23 - (IBAction)ThirdButtonClick:(id)sender {
    24     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
    25     alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){
    26         if (buttonIndex == 1) {
    27             NSLog(@"魔法alertView1003执行ok");
    28         }
    29     };
    30     [alertView show];
    31 }

    我们通过使用Category给UIAlertView扩展了一个block属性,当block被设置后就会调用setCallBack方法,触发self.delegate = self,即主类中的UIAlertView的delegate方法被Category中的方法覆盖。这样不仅有效解决问题,还解决了其他人修改该类的安全性(block被去掉后,原delegate恢复)

    如下不给tag值为1003的UIAlertView设置block,即调用原delegate方法。

     1 - (IBAction)firstButtonClick:(id)sender {
     2     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
     3     alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){
     4         if (buttonIndex == 1) {
     5             NSLog(@"魔法alertView1001执行ok");
     6         }
     7     };
     8     alertView.tag = 1001;
     9     [alertView show];
    10 }
    11 
    12 - (IBAction)secondButtonClick:(id)sender {
    13     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
    14     alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){
    15         if (buttonIndex == 1) {
    16             NSLog(@"魔法alertView1002执行ok");
    17         }
    18     };
    19     alertView.tag = 1002;
    20     [alertView show];
    21 }
    22 
    23 - (IBAction)ThirdButtonClick:(id)sender {
    24     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
    25     alertView.tag = 1003;
    26     [alertView show];
    27 }
    28 
    29 - (IBAction)fourthButtonClick:(id)sender {
    30     UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"title" message:@"message" preferredStyle:UIAlertControllerStyleAlert];
    31     UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"cancel" style:UIAlertActionStyleCancel handler:nil];
    32     UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alertAction){
    33         NSLog(@"如果你是iOS8以上的应用,这个适合你,简单明了");
    34     }];
    35     [alertController addAction:cancelAction];
    36     [alertController addAction:okAction];
    37     [self presentViewController:alertController animated:YES completion:nil];
    38 }
    39 
    40 #pragma mark - delegate method
    41 
    42 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    43 {
    44     if (alertView.tag == 1001) {
    45         if (buttonIndex == 1) {
    46             NSLog(@"普通alertView1001执行ok");
    47         }
    48     } else if (alertView.tag == 1002) {
    49         if (buttonIndex == 1) {
    50             NSLog(@"普通alertView1002执行ok");
    51         }
    52     } else if (alertView.tag == 1003) {
    53         if (buttonIndex == 1) {
    54             NSLog(@"普通alertView1003执行ok");
    55         }
    56     } else if (alertView.tag == 1004) {
    57         if (buttonIndex == 1) {
    58             NSLog(@"普通alertView1004执行ok");
    59         }
    60     }
    61 }

    uialertbyruntimenew

    相关Demo下载:

    https://github.com/ianisme/UIAlertViewBYRuntime_Demo

    总结:

    通过Associated Objects我们有效的解决了UIAlertView的繁琐问题,如果您是开发iOS8以上的应用,建议您弃用UIAlertView,苹果的UIAlertController已经有了更好的解决方案。

  • 相关阅读:
    184. Department Highest Salary【leetcode】sql,join on
    181. Employees Earning More Than Their Managers【leetcode】,sql,inner join ,where
    178. Rank Scores【leetcode】,sql
    177. Nth Highest Salary【leetcode】,第n高数值,sql,limit,offset
    176. Second Highest Salary【取表中第二高的值】,sql,limit,offset
    118. Pascal's Triangle【LeetCode】,java,算法,杨辉三角
    204. Count Primes【leetcode】java,算法,质数
    202. Happy Number【leetcode】java,hashSet,算法
    41. First Missing Positive【leetcode】寻找第一个丢失的整数,java,算法
    删除
  • 原文地址:https://www.cnblogs.com/fengmin/p/5403190.html
Copyright © 2011-2022 走看看