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

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

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

//
//  HMTSecondViewController.h
//  Created by HMT on 14-8-2.
//
#import <UIKit/UIKit.h>

typedef void(^PressValueBlock)(NSString *);
@interface HMTSecondViewController : UIViewController

- (void)pressValueFromSecondToMainWithBlock:(PressValueBlock)pressValue;

@end

//
//  HMTSecondViewController.m
//  Created by HMT on 14-8-2.
//

#import "HMTSecondViewController.h"
#import <objc/runtime.h>

//唯一静态变量key
static char pressValue;

@interface HMTSecondViewController ()

@end

@implementation HMTSecondViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(didBackBarButtonAction:)];
    self.navigationItem.title = @"测试objc";
    self.view.backgroundColor = [UIColor yellowColor];
}

- (void)pressValueFromSecondToMainWithBlock:(PressValueBlock)pressValue{

    /**
     * @see objc_setAssociatedObject
     * 设置关联
     * Sets an associated value for a given object using a given key and association policy.
     *
     * @param object 源对象.
     * @param key 是一个 void 指针,对于每个关联,key必须唯一,通常可以使用一个 static variable.
     * @param value 关联的对象. Pass nil to clear an existing association.
     * @param policy 关联策略,用来指定,关联的对象是 assigned, retained, copied, 还有是否是atomically.
     *
     * @see objc_getAssociatedObject
     * @see objc_removeAssociatedObjects 可以断开所有associative。通常情况下不建议这么做,因为他会断开所有关联。
     */
    objc_setAssociatedObject(self, &pressValue, pressValue, OBJC_ASSOCIATION_COPY);
    
}

- (void)didBackBarButtonAction:(UIBarButtonItem *)backBtn{

    // 获取关联对象
    PressValueBlock pressValue = objc_getAssociatedObject(self, &pressValue);
    if (pressValue) {
        pressValue(@"objc-runtime方式的传值");
    }
    [self.navigationController popViewControllerAnimated:YES];
    
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

//
//  HMTSendButton.h
//  Created by HMT on 14-8-1.
//

#import <UIKit/UIKit.h>

typedef void(^ShareBlock)();
@interface HMTSendButton : UIButton

- (id)initWithClick:(ShareBlock)share;

@end

//
//  HMTSendButton.m
//  Created by HMT on 14-8-1.
//

#import "HMTSendButton.h"
#import <objc/runtime.h>

@implementation HMTSendButton

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (id)initWithClick:(ShareBlock)share{

    if (self = [super init]) {
        
        // oc运行时的关联特性  self 与 share 关联起来
        objc_setAssociatedObject(self, @"share", share, OBJC_ASSOCIATION_COPY);
        self.frame = CGRectMake(130, 200, 60, 40);
        self.backgroundColor = [UIColor redColor];
        [self addTarget:self action:@selector(didClickShareButton) forControlEvents:UIControlEventTouchUpInside];
    }
    
    return self;
    
}

- (void)didClickShareButton{

    // 获得关联对象
    ShareBlock shareBlock = objc_getAssociatedObject(self, @"share");
    if (shareBlock) {
        shareBlock();
    }
    

}

@end

//
//main.m
//
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.title = @"objc";
    self.view.backgroundColor = [UIColor cyanColor];
    __weak __typeof(self) weakSelf = self;
    self.shareButton = [[HMTSendButton alloc] initWithClick:^{
      
        HMTSecondViewController *secondVC = [[HMTSecondViewController alloc] init];
        [secondVC pressValueFromSecondToMainWithBlock:^(NSString *value) {
            
            weakSelf.objcTestLabel.text = value;
            
        }];
        [weakSelf.navigationController pushViewController:secondVC animated:YES];
        
    }];
    [self.view addSubview:_shareButton];
    
    self.objcTestLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 300, 200, 40)];
    self.objcTestLabel.text = @"初始值";
    [self.view addSubview:_objcTestLabel];
    
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值