天天看点

<objc/runtime.h>中Associative机制(在button以及block传值)

转自:http://blog.csdn.net/hmt20130412/article/details/38349969 

@前段时间面试找工作的时候,面试官问我有没有了解OC语言的动态性,objc/runtime是什么,当时的我真的是一头雾水,只是知道OC动态性,其余的还真没实际的用到过.

            @回去后百度下:objective-c有两个扩展机制:category和associative。我们可以通过category来扩展方法,但是它有个很大的局限性,不能扩展属性。于是,就有了专门用来扩展属性的机制:associative。category比较常见,而associative就用的比较少。associative的主要原理,就是把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分。使用关联,我们可以不用修改类的定义而为其对象增加存储空间。这在我们无法访问到类的源码的时候或者是考虑到二进制兼容性的时候是非常有用。关联是基于关键字的,因此,我们可以为任何对象增加任意多的关联,每个都使用不同的关键字即可。关联是可以保证被关联的对象在关联对象的整个生命周期都是可用的(在垃圾自动回收环境下也不会导致资源不可回收).

[objc] view plaincopy

  1. //  
  2. //  HMTSecondViewController.h  
  3. //  Created by HMT on 14-8-2.  
  4. //  
  5. #import <UIKit/UIKit.h>  
  6. typedef void(^PressValueBlock)(NSString *);  
  7. @interface HMTSecondViewController : UIViewController  
  8. - (void)pressValueFromSecondToMainWithBlock:(PressValueBlock)pressValue;  
  9. @end  
  10. //  
  11. //  HMTSecondViewController.m  
  12. //  Created by HMT on 14-8-2.  
  13. //  
  14. #import "HMTSecondViewController.h"  
  15. #import <objc/runtime.h>  
  16. //唯一静态变量key  
  17. static char pressValue;  
  18. @interface HMTSecondViewController ()  
  19. @end  
  20. @implementation HMTSecondViewController  
  21. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
  22. {  
  23.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
  24.     if (self) {  
  25.         // Custom initialization  
  26.     }  
  27.     return self;  
  28. }  
  29. - (void)viewDidLoad  
  30. {  
  31.     [super viewDidLoad];  
  32.     // Do any additional setup after loading the view.  
  33.     self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(didBackBarButtonAction:)];  
  34.     self.navigationItem.title = @"测试objc";  
  35.     self.view.backgroundColor = [UIColor yellowColor];  
  36. }  
  37. - (void)pressValueFromSecondToMainWithBlock:(PressValueBlock)pressValue{  
  38.     objc_setAssociatedObject(self, &pressValue, pressValue, OBJC_ASSOCIATION_COPY);  
  39. }  
  40. - (void)didBackBarButtonAction:(UIBarButtonItem *)backBtn{  
  41.     // 获取关联对象  
  42.     PressValueBlock pressValue = objc_getAssociatedObject(self, &pressValue);  
  43.     if (pressValue) {  
  44.         pressValue(@"objc-runtime方式的传值");  
  45.     }  
  46.     [self.navigationController popViewControllerAnimated:YES];  
  47. }  
  48. - (void)didReceiveMemoryWarning  
  49. {  
  50.     [super didReceiveMemoryWarning];  
  51.     // Dispose of any resources that can be recreated.  
  52. }  
  53. @end  
  54. //  
  55. //  HMTSendButton.h  
  56. //  Created by HMT on 14-8-1.  
  57. //  
  58. #import <UIKit/UIKit.h>  
  59. typedef void(^ShareBlock)();  
  60. @interface HMTSendButton : UIButton  
  61. - (id)initWithClick:(ShareBlock)share;  
  62. @end  
  63. //  
  64. //  HMTSendButton.m  
  65. //  Created by HMT on 14-8-1.  
  66. //  
  67. #import "HMTSendButton.h"  
  68. #import <objc/runtime.h>  
  69. @implementation HMTSendButton  
  70. - (id)initWithFrame:(CGRect)frame  
  71. {  
  72.     self = [super initWithFrame:frame];  
  73.     if (self) {  
  74.         // Initialization code  
  75.     }  
  76.     return self;  
  77. }  
  78. - (id)initWithClick:(ShareBlock)share{  
  79.     if (self = [super init]) {  
  80.         // oc运行时的关联特性  self 与 share 关联起来  
  81.         objc_setAssociatedObject(self, @"share", share, OBJC_ASSOCIATION_COPY);  
  82.         self.frame = CGRectMake(130, 200, 60, 40);  
  83.         self.backgroundColor = [UIColor redColor];  
  84.         [self addTarget:self action:@selector(didClickShareButton) forControlEvents:UIControlEventTouchUpInside];  
  85.     }  
  86.     return self;  
  87. }  
  88. - (void)didClickShareButton{  
  89.     // 获得关联对象  
  90.     ShareBlock shareBlock = objc_getAssociatedObject(self, @"share");  
  91.     if (shareBlock) {  
  92.         shareBlock();  
  93.     }  
  94. }  
  95. @end  
  96. //  
  97. //main.m  
  98. //  
  99. - (void)viewDidLoad  
  100. {  
  101.     [super viewDidLoad];  
  102.     self.navigationItem.title = @"objc";  
  103.     self.view.backgroundColor = [UIColor cyanColor];  
  104.     __weak __typeof(self) weakSelf = self;  
  105.     self.shareButton = [[HMTSendButton alloc] initWithClick:^{  
  106.         HMTSecondViewController *secondVC = [[HMTSecondViewController alloc] init];  
  107.         [secondVC pressValueFromSecondToMainWithBlock:^(NSString *value) {  
  108.             weakSelf.objcTestLabel.text = value;  
  109.         }];  
  110.         [weakSelf.navigationController pushViewController:secondVC animated:YES];  
  111.     }];  
  112.     [self.view addSubview:_shareButton];  
  113.     self.objcTestLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 300, 200, 40)];  
  114.     self.objcTestLabel.text = @"初始值";  
  115.     [self.view addSubview:_objcTestLabel];  
  116. }  

继续阅读