07.Objective-C 关联对象

2021-02-07  本文已影响0人  ProfessorFan

问题

  1. 分类中可以添加属性吗?
  2. 整么才能使分类中的属性,像正常类的属性一样使用?
  3. 关联对象的本质

答案

  1. 分类中可以添加属性吗?
    答案是肯定得分类中肯定可以添加属性,只是在分类中添加属性,不会向正常类中添加属性一样,自动生成实例变量,还有setter,get 方法
struct _category_t {
    const char *name;
    struct _class_t *cls;
    const struct _method_list_t *instance_methods;
    const struct _method_list_t *class_methods;
    const struct _protocol_list_t *protocols;
    const struct _prop_list_t *properties;  # 这个就是分类的结构,里面存在属性这个list
};
  1. 整么才能使分类中的属性,像正常类的属性一样使用?
    但是是关联对象,可以使分类中有向类一样的正常属性
    具体代码如下:

#  这个是分类的 interface 
@interface FanPerson(Test)

@property (copy, nonatomic) NSString *name;

@end

# 这个是分类的implement

@implement FanPerson(Test)
- (void)setName:(NSString *)name
{
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)name
{
    // 隐式参数
    // _cmd == @selector(name)
    return objc_getAssociatedObject(self, _cmd);
}

@end
  1. 关联对象的本质

关键类的在objc 源码中的定义:

class AssociationsManager {
    using Storage = ExplicitInitDenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap>;
    static Storage _mapStorage;

public:
    AssociationsManager()   { AssociationsManagerLock.lock(); }
    ~AssociationsManager()  { AssociationsManagerLock.unlock(); }

    AssociationsHashMap &get() {
        return _mapStorage.get();
    }

    static void init() {
        _mapStorage.init();
    }
};

typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap;
typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMap;

class ObjcAssociation {
    uintptr_t _policy;
    id _value;
}
上一篇下一篇

猜你喜欢

热点阅读