您的位置:首页 > 其它

Runtime --- 类增加实例变量

2016-04-28 14:17 267 查看
有这么一个需求,为系统的类添加一个方法,可能大家都会想到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里设置下关联值,就可以为系统类动态增加属性。运行一下,很轻松的就运行起来了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  runtime 类实例 动态