在没有介绍关联对象之前,先看一道面试题
Category能否添加成员变量?如果可以,如何给Category添加成员变量?
在Cateogry底层学习笔记中,注意的第一条category里面不能添加成员变量。但是可以通过关联对象间接的实现成员变量效果。
在Category中,给分类添加属性方法,只会给分类添加属性的set方法和get方法的声明。不会像在类中,给类添加属性,同时生成成员变量,set方法的声明和实现以及get方法的声明和实现。我们来看下Category的底层结构图:
Category的底层结构
在Category的底层结构中,包括实例方法列表
method_list_t、类方法列表method_list_t、协议列表protocol_list_t、属性列表property_list_t。但是没有成员变量列表ivars。所以要实现成员变量功能,可以通过其他方式,关联对象就是其中的一种方式。
我们先看下,关联对象的使用方式
main.m的调用方式
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Person+Test3.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person = [[Person alloc] init];
person.name = @"糖糖";
NSLog(@"%d %d %@",person.weight,person.height,person.name);
}
return 0;
}
类文件
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
#import "Person.h"
@implementation Person
@end
在分类中使用关联对象
#import "Person.h"
@interface Person (Test3)
@property (nonatomic, copy) NSString *name;
@end
#import "Person+Test3.h"
#import <objc/runtime.h>
@implementation Person (Test3)
- (void)setName:(NSString *)name{
objc_setAssociatedObject(self,@selector(name),name,OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self,_cmd);
}
@end
关联对象的原理
实现关联对象技术的核心对象有
AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjcAssociation
AssociationsManager内部有static AssociationsHashMap *_map;
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) {
_object_set_associative_reference(object, (void *)key, value, policy);
}
在AssociationsHashMap的内部,包含ObjectAssociationMap。
class AssociationsHashMap : public unordered_map<disguised_ptr_t,
ObjectAssociationMap *, DisguisedPointerHash,
DisguisedPointerEqual, AssociationsHashMapAllocator> {
...
};
在ObjectAssociationMap内部包含ObjcAssociation。
class ObjectAssociationMap : public std::map<void *, ObjcAssociation, ObjectPointerLess, ObjectAssociationMapAllocator> {
...
};
在ObjcAssociation内部,有两个重要属性_policy,_value;
class ObjcAssociation {
uintptr_t _policy;
id _value;
...
};
在objc_setAssociatedObject(object, const void *key, id value, objc_AssociationPolicy policy)方法中,传入的参数value,policy,最后传入ObjcAssociation内部。
四个核心对象的关系图
-
AssociationsManager内部的AssociationsHashMap有成对的keydisguised_ptr_t和valueObjectAssociationMap值。 - 在
ObjectAssociationMap内部也有成对的key值void *和value值ObjectAssociation - 在
ObjectAssociation内部有value,policy。
在objc_setAssociatedObject(object, const void *key, id value, objc_AssociationPolicy policy)方法内, - object是key值
disguised_ptr_t; - const void *key是key值
void *; - id value 是
ObjectAssociation内部的value,bjc_AssociationPolicy policy是ObjectAssociation内部的policy`。











网友评论