关联对象学习

2018-11-11  本文已影响0人  朝夕向背

在没有介绍关联对象之前,先看一道面试题

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)方法中,传入的参数valuepolicy,最后传入ObjcAssociation内部。

四个核心对象的关系图
上一篇 下一篇

猜你喜欢

热点阅读