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已经有了更好的解决方案。

  • 相关阅读:
    WPA/WPA2无法暴力破解
    被书本知识所边缘化的软件工程师
    栈和队列
    Oracle update 之部分更新
    SAAS之初体验
    Entity Framework
    ResourceWriter和ResxResourceWriter的區別
    C#中將顏色轉換成網頁16進制顏色代碼
    Javascript功能代码收集(不断更新中...)
    .net1.1转换成更高版本的问题总结
  • 原文地址:https://www.cnblogs.com/fengmin/p/5403190.html
Copyright © 2011-2022 走看看