国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > 综合技术 > ##oc在类别里给类加属性以及原理

##oc在类别里给类加属性以及原理

来源:程序员人生   发布时间:2015-01-07 08:58:33 阅读次数:3467次

oc在种别里给类加属性和原理

如何在种别里给类加属性呢,有鸭子样子的我们就认为他是鸭子了.

@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;
}
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生