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

来源:互联网 发布:a算法八数码 编辑:程序博客网 时间:2024/06/05 22:20

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

 

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

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

[objc] view plaincopy
  1. //  
  2. //  HMTSecondViewController.h  
  3. //  Created by HMT on 14-8-2.  
  4. //  
  5. #import <UIKit/UIKit.h>  
  6.   
  7. typedef void(^PressValueBlock)(NSString *);  
  8. @interface HMTSecondViewController : UIViewController  
  9.   
  10. - (void)pressValueFromSecondToMainWithBlock:(PressValueBlock)pressValue;  
  11.   
  12. @end  
  13.   
  14. //  
  15. //  HMTSecondViewController.m  
  16. //  Created by HMT on 14-8-2.  
  17. //  
  18.   
  19. #import "HMTSecondViewController.h"  
  20. #import <objc/runtime.h>  
  21.   
  22. //唯一静态变量key  
  23. static char pressValue;  
  24.   
  25. @interface HMTSecondViewController ()  
  26.   
  27. @end  
  28.   
  29. @implementation HMTSecondViewController  
  30.   
  31. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
  32. {  
  33.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
  34.     if (self) {  
  35.         // Custom initialization  
  36.     }  
  37.     return self;  
  38. }  
  39.   
  40. - (void)viewDidLoad  
  41. {  
  42.     [super viewDidLoad];  
  43.     // Do any additional setup after loading the view.  
  44.     self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(didBackBarButtonAction:)];  
  45.     self.navigationItem.title = @"测试objc";  
  46.     self.view.backgroundColor = [UIColor yellowColor];  
  47. }  
  48.   
  49. - (void)pressValueFromSecondToMainWithBlock:(PressValueBlock)pressValue{  
  50.   
  51.     /** 
  52.      * @see objc_setAssociatedObject 
  53.      * 设置关联 
  54.      * Sets an associated value for a given object using a given key and association policy. 
  55.      * 
  56.      * @param object 源对象. 
  57.      * @param key 是一个 void 指针,对于每个关联,key必须唯一,通常可以使用一个 static variable. 
  58.      * @param value 关联的对象. Pass nil to clear an existing association. 
  59.      * @param policy 关联策略,用来指定,关联的对象是 assigned, retained, copied, 还有是否是atomically. 
  60.      * 
  61.      * @see objc_getAssociatedObject 
  62.      * @see objc_removeAssociatedObjects 可以断开所有associative。通常情况下不建议这么做,因为他会断开所有关联。 
  63.      */  
  64.     objc_setAssociatedObject(self, &pressValue, pressValue, OBJC_ASSOCIATION_COPY);  
  65.       
  66. }  
  67.   
  68. - (void)didBackBarButtonAction:(UIBarButtonItem *)backBtn{  
  69.   
  70.     // 获取关联对象  
  71.     PressValueBlock pressValue = objc_getAssociatedObject(self, &pressValue);  
  72.     if (pressValue) {  
  73.         pressValue(@"objc-runtime方式的传值");  
  74.     }  
  75.     [self.navigationController popViewControllerAnimated:YES];  
  76.       
  77. }  
  78.   
  79. - (void)didReceiveMemoryWarning  
  80. {  
  81.     [super didReceiveMemoryWarning];  
  82.     // Dispose of any resources that can be recreated.  
  83. }  
  84.   
  85. @end  
  86.   
  87. //  
  88. //  HMTSendButton.h  
  89. //  Created by HMT on 14-8-1.  
  90. //  
  91.   
  92. #import <UIKit/UIKit.h>  
  93.   
  94. typedef void(^ShareBlock)();  
  95. @interface HMTSendButton : UIButton  
  96.   
  97. - (id)initWithClick:(ShareBlock)share;  
  98.   
  99. @end  
  100.   
  101. //  
  102. //  HMTSendButton.m  
  103. //  Created by HMT on 14-8-1.  
  104. //  
  105.   
  106. #import "HMTSendButton.h"  
  107. #import <objc/runtime.h>  
  108.   
  109. @implementation HMTSendButton  
  110.   
  111. - (id)initWithFrame:(CGRect)frame  
  112. {  
  113.     self = [super initWithFrame:frame];  
  114.     if (self) {  
  115.         // Initialization code  
  116.     }  
  117.     return self;  
  118. }  
  119.   
  120. - (id)initWithClick:(ShareBlock)share{  
  121.   
  122.     if (self = [super init]) {  
  123.           
  124.         // oc运行时的关联特性  self 与 share 关联起来  
  125.         objc_setAssociatedObject(self@"share", share, OBJC_ASSOCIATION_COPY);  
  126.         self.frame = CGRectMake(1302006040);  
  127.         self.backgroundColor = [UIColor redColor];  
  128.         [self addTarget:self action:@selector(didClickShareButton) forControlEvents:UIControlEventTouchUpInside];  
  129.     }  
  130.       
  131.     return self;  
  132.       
  133. }  
  134.   
  135. - (void)didClickShareButton{  
  136.   
  137.     // 获得关联对象  
  138.     ShareBlock shareBlock = objc_getAssociatedObject(self@"share");  
  139.     if (shareBlock) {  
  140.         shareBlock();  
  141.     }  
  142.       
  143.   
  144. }  
  145.   
  146. @end  
  147.   
  148. //  
  149. //main.m  
  150. //  
  151. - (void)viewDidLoad  
  152. {  
  153.     [super viewDidLoad];  
  154.     self.navigationItem.title = @"objc";  
  155.     self.view.backgroundColor = [UIColor cyanColor];  
  156.     __weak __typeof(self) weakSelf = self;  
  157.     self.shareButton = [[HMTSendButton alloc] initWithClick:^{  
  158.         
  159.         HMTSecondViewController *secondVC = [[HMTSecondViewController alloc] init];  
  160.         [secondVC pressValueFromSecondToMainWithBlock:^(NSString *value) {  
  161.               
  162.             weakSelf.objcTestLabel.text = value;  
  163.               
  164.         }];  
  165.         [weakSelf.navigationController pushViewController:secondVC animated:YES];  
  166.           
  167.     }];  
  168.     [self.view addSubview:_shareButton];  
  169.       
  170.     self.objcTestLabel = [[UILabel alloc] initWithFrame:CGRectMake(6030020040)];  
  171.     self.objcTestLabel.text = @"初始值";  
  172.     [self.view addSubview:_objcTestLabel];  
  173.       
  174. }  
0 0
原创粉丝点击