标签:
上篇文章写的是Runtime的一个入门教程,刚哥问我那个Associated Objects加回调是啥时候用,那我就来告诉你啦!我们在使用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的判断,太繁琐了。
下面我们使用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 }
https://github.com/ianisme/UIAlertViewBYRuntime_Demo
通过Associated Objects我们有效的解决了UIAlertView的繁琐问题,如果您是开发iOS8以上的应用,建议您弃用UIAlertView,苹果的UIAlertController已经有了更好的解决方案。
Objective-C Runtime之着魔的UIAlertView
标签:
原文地址:http://www.cnblogs.com/fengmin/p/5403190.html