面试题
Q:分类中到底能否实现属性?
A:
·1.如果把属性理解为通过方法访问的实例变量,答案是不能,因为分类不能为类增加额外的实例变量。会提示黄色警告,使用的时候运行到这里会crash。
·2.如果属性只是一个存取方法,那么分类是可以实现属性的。
这篇文章主要讲的是使用runtime里面的AssociatedObject关联对象的方法来模拟『属性』的存取方法,也就是 objc_getAssociatedObject 以及 objc_setAssociatedObject两个方法 。
id objc_getAssociatedObject(id object, const void *key);
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
在使用这两个方法之前需要在分类里面导入#import <objc/runtime.h> 或者 #import <objc/message.h> //这两种都可以。
说一下每个参数的含义:
- 第一个方法的两个参数:
1.源对象(self)
2.关联时用来标记是哪一个属性的key
- 第二个方法的参数:
1.源对象(self)
2.关联时用来标记是哪一个属性的key
3.关联的对象
4.关联策略(OBJC_ASSOCIATION_RETAIN_NONATOMIC)
关联策略是个枚举值
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, //关联对象的属性是弱引用
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //关联对象的属性是强引用并且关联对象不使用原子性
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //关联对象的属性是copy并且关联对象不使用原子性
OBJC_ASSOCIATION_RETAIN = 01401, //关联对象的属性是copy并且关联对象使用原子性
OBJC_ASSOCIATION_COPY = 01403 //关联对象的属性是copy并且关联对象使用原子性
};
名称 | 对应的修饰词 |
---|---|
objc_AssociationPolicy | modifier |
OBJC_ASSOCIATION_ASSIGN | assign |
OBJC_ASSOCIATION_RETAIN_NONATOMIC | nonatomic, strong |
OBJC_ASSOCIATION_COPY_NONATOMIC | nonatomic, copy |
OBJC_ASSOCIATION_RETAIN | atomic, strong |
OBJC_ASSOCIATION_COPY | atomic, copy |
也就是你定义属性的时候给的修饰词,譬如:
@property(nonatomic, strong)UIView *loadView;
上面这个属性关联策略也就是 OBJC_ASSOCIATION_RETAIN_NONATOMIC
@property(nonatomic, copy)NSString *name;
关联策略也就是 OBJC_ASSOCIATION_COPY_NONATOMIC
#import "UIView+lf.h"
#import <objc/runtime.h>
static NSString *loadViewKey = @"loadViewKey"; //loadViewKey的key
@implementation UIView (lf)
-(void)setLoadView:(UIView *)loadView{
objc_setAssociatedObject(self, &loadViewKey, loadView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(UIView *)loadView{
return objc_getAssociatedObject(self, &loadViewKey);
}
@end
有时候我们也会看到有人用下面的写法
#import "UIView+lf.h"
#import <objc/runtime.h>
static NSString *nameKey = @"nameKey"; //name的key
@implementation UIView (lf)
-(NSString *)name{
return objc_getAssociatedObject(self, _cmd);
}
-(void)setName:(NSString *)name{
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end
这里的 _cmd 代指当前方法的选择子,也就是 @selector(name)。第二句代码中出现 @selector(name),这里它就调用第一句代码了, @selector直接返回SEL,则获取到name的方法名,则为第一句代码返回的值.
网友评论