【知识总结】category探索 — 如何在分类中添加一个属性(runtime)

添加属性的本质:

对象添加属性,并不是在对象中为属性分配响应的内存,而是通过一个指针指向这个属性,本质就是关联这个属性
因此,在分类中我们可以通过关联的方式添加属性


我们新建一个 UIView 的分类,在分类中添加属性和方法

@interface UIView (Extension)
@property (nonatomic, strong) NSString *property;
- (void)show;
@end

在 m 文件中实现 show 方法

#import "UIView+Extension.h"
@implementation UIView (Extension)
- (void)show
{
NSLog(@"%@", self.property);
}

@end

下面,我们来测试一下,在viewController中使用我们的分类

- (void)viewDidLoad {
[super viewDidLoad];

UIView *view = [[UIView alloc] init];
view.property = @"我是分类中添加的属性";
[view show];
}

运行,可以看到程序奔溃了,查看奔溃信息:

奔溃信息提示,我们的 分类中添加的属性, setProperty:方法没有实现

接下来,我们尝试实现setProperty:方法,但是会遇到下面的问题

系统提示我们使用 @dynamic 实现分类这个分类

接着,我们尝试使用 @dynamic 实现,如下:

上面,我们一直才尝试实现 setProperty: 方法,但是由于分类的特殊性
在分类中声明@property,只会生成方法的声明,不会生成方法的实现和带有_下划线的成员变量
而且我们尽量去尝试自己实现,系统也是不允许我们这么做的

于是我们使用runtime来实现为分类添加属性这一需求


使用到运行时,首先我们要导入 头文件

#import "UIView+Extension.h"
#import 

@implementation UIView (Extension)

- (void)setProperty:(NSString *)property
{
NSLog(@"实现 setProperty 方法");
objc_setAssociatedObject(self, @selector(property), property, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (NSObject *)property {

return objc_getAssociatedObject(self, @selector(property));

}

- (void)show
{
NSLog(@"show:%@", self.property);
}
@end

运行程序,查看结果

我们已经成功的为分类添加了一个属性

分析上面用到的两个运行时方法

void objc_setAssociatedObject(id object, const voidvoid *key, id value, objc_AssociationPolicy policy)

id objc_getAssociatedObject(id object, const voidvoid *key)

void objc_removeAssociatedObjects(id object)

把一个value关联到另外一个object里,类似NSDictionary的 setValue:forKey 。
用 objc_setAssociatedObject 关联以后,用 objc_getAssociatedObject 取出使用。
objc_AssociationPolicy 属性 是设定该value在object内的属性,即 assgin, (retain,nonatomic)...等

1. //policy
2. enum {
3. OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
4. OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
5. * The association is not made atomically. */
6. OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
7. * The association is not made atomically. */
8. OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
9. * The association is made atomically. */
10. OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
11. * The association is made atomically. */
12. };
13.
14. /// Type to specify the behavior of an association.
15. typedef uintptr_t objc_AssociationPolicy;

我们可以通过这个运行方法,实现 button 事件的 block 实现

相关资料:
用objc/runtime给类别扩展属性 http://www.jianshu.com/p/84de8a931adf
objc_setAssociatedObject与Block的简单使用 http://www.jianshu.com/p/35df1ba1f107


有一个推荐添加读写属性的方法,如下

【知识总结】category探索 — 如何在分类中添加一个属性(runtime)_第1张图片
Paste_Image.png

这种方法的缺陷是,分类的实现不能独立实现在一个分类文件中,必须实现在同一个文件中,局限性就很大了

你可能感兴趣的:(【知识总结】category探索 — 如何在分类中添加一个属性(runtime))