如何在种别里给类加属性呢,有鸭子样子的我们就认为他是鸭子了.
@interface NSObject (XY)
@property (nonatomic, strong) id tempObject;
@end
@implementation NSObject (XY)
@dynamic tempObject;
- (id)tempObject
- {
id object = objc_getAssociatedObject(self, NSObject_key_tempObject);
return object;
}
- (void)setTempObject:(id)tempObject
- {
[self willChangeValueForKey:@"tempObject"];
objc_setAssociatedObject(self, NSObject_key_tempObject, tempObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self didChangeValueForKey:@"tempObject"];
}
@end
属性取变量是直接偏移地址得到,关联是取了2次map.
下面来看1下set get 还有dealloc时候产生的事情吧
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) {
#if SUPPORT_GC
if (UseGC) {
if ((policy & OBJC_ASSOCIATION_COPY_NONATOMIC) == OBJC_ASSOCIATION_COPY_NONATOMIC) {
value = objc_msgSend(value, SEL_copy);
}
auto_zone_set_associative_ref(gc_zone, object, (void *)key, value);
} else
#endif
{
// Note, creates a retained reference in non-GC.
_object_set_associative_reference(object, (void *)key, value, policy);
}
}
PRIVATE_EXTERN void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) {
// retain the new value (if any) outside the lock.
uintptr_t old_policy = 0; // NOTE: old_policy is always assigned to when old_value is non-nil.
id new_value = value ? acquireValue(value, policy) : nil, old_value = nil;
{
// 有个管理关联的单利
AssociationsManager manager;
AssociationsHashMap &associations(manager.associations());
if (new_value) {
// 如果有值
// break any existing association.
AssociationsHashMap::iterator i = associations.find(object);
if (i != associations.end()) {
// 如果在map里有object的话
// secondary table exists
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
// 如果在ObjectAssociationMap里没找到key对应的值就new1个,塞进去
ObjcAssociation &old_entry = j->second;
old_policy = old_entry.policy;
old_value = old_entry.value;
old_entry.policy = policy;
old_entry.value = new_value;
} else {
// 找到了就直接赋值
(*refs)[key] = ObjcAssociation(policy, new_value);
}
} else {
// 没有object就创建
// create the new association (first time).
ObjectAssociationMap *refs = new ObjectAssociationMap;
associations[object] = refs;
(*refs)[key] = ObjcAssociation(policy, new_value);
_class_setInstancesHaveAssociatedObjects(_object_getClass(object));
}
} else {
// 没值就清空
// setting the association to nil breaks the association.
AssociationsHashMap::iterator i = associations.find(object);
if (i != associations.end()) {
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
ObjcAssociation &old_entry = j->second;
old_policy = old_entry.policy;
old_value = (id) old_entry.value;
refs->erase(j);
}
}
}
}
// release the old value (outside of the lock).
if (old_value) releaseValue(old_value, old_policy);
}
id objc_getAssociatedObject(id object, const void *key) {
#if SUPPORT_GC
if (UseGC) {
return auto_zone_get_associative_ref(gc_zone, object, (void *)key);
} else
#endif
{
return _object_get_associative_reference(object, (void *)key);
}
}
PRIVATE_EXTERN id _object_get_associative_reference(id object, void *key) {
id value = nil;
uintptr_t policy = OBJC_ASSOCIATION_ASSIGN;
{
AssociationsManager manager;
AssociationsHashMap &associations(manager.associations());
AssociationsHashMap::iterator i = associations.find(object);
if (i != associations.end()) {
// 取值的时候就在AssociationsHashMap里面先找到object
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
// 然后找到的key对应的值
ObjcAssociation &entry = j->second;
value = (id)entry.value;
policy = entry.policy;
if (policy & OBJC_ASSOCIATION_GETTER_RETAIN) objc_msgSend(value, SEL_retain);
}
}
}
if (value && (policy & OBJC_ASSOCIATION_GETTER_AUTORELEASE)) {
objc_msgSend(value, SEL_autorelease);
}
return value;
}
void *objc_destructInstance(id obj)
{
if (obj) {
Class isa = _object_getClass(obj);
if (_class_hasCxxStructors(isa)) {
object_cxxDestruct(obj);
}
// 在释放的代码里,释放关联的属性
if (_class_instancesHaveAssociatedObjects(isa)) {
_object_remove_assocations(obj);
}
if (!UseGC) objc_clear_deallocating(obj);
}
return obj;
}
上一篇 第九话-原型模式