添加属性的本质:
对象添加属性,并不是在对象中为属性分配响应的内存,而是通过一个指针指向这个属性,本质就是关联这个属性
因此,在分类中我们可以通过关联的方式添加属性
我们新建一个 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来实现为分类添加属性这一需求
使用到运行时,首先我们要导入 <objc/runtime.h> 头文件
#import "UIView+Extension.h"
#import <objc/runtime.h>
@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
有一个推荐添加读写属性的方法,如下
Paste_Image.png这种方法的缺陷是,分类的实现不能独立实现在一个分类文件中,必须实现在同一个文件中,局限性就很大了
网友评论