码迷,mamicode.com
首页 > 其他好文 > 详细

Runtime的实践——给一个类添加属性(关联对象)

时间:2016-05-11 11:28:10      阅读:245      评论:0      收藏:0      [点我收藏+]

标签:

相关文章:
《Runtime的初步认识——结构体与类》
《Runtime的初步认识——消息机制》

一提到给一个类添加点什么,我们有可能首先就想到类别(Category)。那么我们就弄一下。

利用 Category 给现有的类添加属性

比如我们要给一个 NSArray 添加一个属性叫做NSString *name。

我们首先新建一个Objective-C文件。

File: Name

File Type:Category

Class:NSArray

然后我们在NSArray+Name.h里面写

@interface NSArray (Name)

@property (nonatomic, copy) NSString *name;

@end

于是我们就给NSArray这个类添加了一个NSString类型的name

现在我们导入NSArray+Name.h文件去实现一下代码验证一下

NSArray *array = [[NSArray alloc] init];

array.name = @"test";

NSLog(@"%@", array.name);

我们新建了一个NSArray,并把@"test"赋值给了array的属性中。

然后输出看看这个属性是否成功赋值。

于是你很开心地按下了command+R,发现这家伙奔溃了,奔溃原因:

[__NSArray0 setName:]: unrecognized selector sent to instance 0x100102f80

NSArray并没有这个setName:这个方法,仔细一看 Xcode 还给我们两个警告。

于是我们进入NSArray+Name.m文件写上 get 方法和 set 方法:

@implementation NSArray (Name)

- (void)setName:(NSString *)name {
    _name = name;
}


- (NSString *)name {
    return _name;
}
@end

很好,两个错误,因为并没有实例变量。或许你觉得可以添加一个扩展。于是你写了一个扩展并且给他添加了一个实例变量NSString *name,然后这次连编译都不通过。

于是你哭了/(ㄒoㄒ)/~~

Category只能给已有的类添加方法,不能添加实例变量

那现在怎么办呢?难道我们之前的问题就解决不了了?

这个时候runtime的作用就体现出来了。之前我们说过,它可以动态的去修改我们创建的结构体(也就已经声明的类)。

利用 Runtime 和 Category 给现有的类添加属性

关联对象

关联对象是只将一个对象a利用一个key绑定一个对象b,之后a就可以利用这个key获取到这个对象b

同时,a可以二次绑定同一个key,并且会替换之前被绑定的对象。之后再通过key获取对象,就是一个新绑定的值了。

是不是感觉和普通的属性很像?可以赋值,可以取值,可以重复赋值然后覆盖。

的确,只是调用一个函数而已。

函数

Runtime 给了我们两个函数来实现关联对象,你只需要#import <objc/runtime.h>就可以使用这两个函数了。

这两个函数分别是:

//set function
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);

//get function
id objc_getAssociatedObject(id object, const void *key);

赋值函数

来看看 set 函数里的东西

  • object 要持有“别的对象”的对象,这里也就是指a
  • key 关联关键字,是一个字符串常亮,是一个地址(这里注意,地址必须是不变的,地址不同但是内容相同的也不算同一个key)
  • value 也就是值,你可以猜的出应该是值b
  • policy 这是一个枚举,你可以点进去看看这个枚举是什么:
    • OBJC_ASSOCIATION_ASSIGN
    • OBJC_ASSOCIATION_RETAIN_NONATOMIC
    • OBJC_ASSOCIATION_COPY_NONATOMIC
    • OBJC_ASSOCIATION_RETAIN
    • OBJC_ASSOCIATION_COPY

如果你了解 Objective-C,那你一定知道上面这些枚举的作用了。

所以,我们就可以在前面的NSArray的分类里这么写

- (void)setName:(NSString *)name {
    objc_setAssociatedObject(self, "name", name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

取值函数

现在来看看 get 函数里的东西

  • object 持有“别的对象”的对象,这里指a
  • key 关联关键字

看完 set 函数之后,get 函数就显而易见了!这里不用多解释,立马就可以写代码

- (NSString *)name {
    return objc_getAssociatedObject(self, "name");
}

验证结果

运行demo,成功输出如下内容:

2016-05-11 09:22:32.950 runtime+Category demo[923:36795] test
Program ended with exit code: 0

说明我们给 array 赋值的结果成功保留下来,下一次去取值可以成功取到上一次保存的值了。

Runtime的实践——给一个类添加属性(关联对象)

标签:

原文地址:http://blog.csdn.net/ruiwang321/article/details/51371754

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!