Runtime --- 类增加实例变量

    有这么一个需求,为系统的类添加一个方法,可能大家都会想到category;可如果,要为类添加一个实例呢?我们都知道,category不能添加实例对象,那应该怎么办呢? 还好,Objective-C有一项强大的特性可以解决此问题,这就是“关联对象”(Associated Object)

主要通过三个方法来管理:
1.void objc_setAssociatedObject (id object, void*key, id value, objc_AssociationPolicy policy)
此方法以给定的键和策略为对象设置关联对象值

2.id objc_getAssociatedObject (id object, void*key)
此方法根据给定的键从某对象中获取相应的关联对象值

3.void objc_removeAssociatedObjects(id object)
此方法移除指定对象的全部关联对象

观察上面三种方法,是不是发现和NSDictionary存、取、删除数据很像,我们可以这样加深理解。不过注意,两者有个重要差别,设置关联对象用的键是个“不透明指针”,就是说其指向的数据结构不局限于某种特定类型的指针。
下面上代码:

下面上代码:

//
//  UIView+FlyView.h
//  runtime_property
//
//  Created by fly on 16/4/25.
//  Copyright © 2016年 HelloBaby. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIView (FlyView)

@property (nonatomic, copy) NSString *tagStr;

@end
#import "ViewController.h"
#import "UIView+FlyView.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *flyView      = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 50, 50)];
    flyView.backgroundColor = [UIColor yellowColor];
    flyView.tagStr          = @"1";

    [self.view addSubview:flyView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end
    我们知道,UIView有个Tag属性,支持int类型,可是我想让他拥有一个支持NString类型,所以我在category给他增加tagStr属性。这样在创建时没报错,但是在运行时会发现,崩溃,错误原因`’-[UIView setTagStr:]: unrecognized selector sent to instance 0x7f856347baf0’
    category不支持实例变量,虽然我们创建的是属性,可底层还是会调用setter方法设置实例的。这种情况下,我们就可以通过上面轻松实现
#import "UIView+FlyView.h"
#import <objc/runtime.h>

@implementation UIView (FlyView)

- (void)setTagStr:(NSString *)tagStr
{
    /*  参数
     *  第一个参数:将关联值设置到的实例
     *  第二个参数:关联值的标识key,不只是NSString,它支持任何类型
     *  第三个参数:关联值自身
     *  第四个参数:关联属性的存储策略,枚举,对应我们申明属性时属性的属性·
     */

    objc_setAssociatedObject(self, @selector(tagStr), tagStr,  OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (NSString *)tagStr
{
    return objc_getAssociatedObject(self, @selector(tagStr));
}
@end
    其他的不需要变,我们只需要在.m里设置下关联值,就可以为系统类动态增加属性。运行一下,很轻松的就运行起来了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值