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

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.

下面来看一下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对应的值就new一个,塞进去
                    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;
}
时间: 2024-10-15 09:14:18

##oc在类别里给类加属性以及原理的相关文章

oc学习之对象作为类的属性

对象做为类的属性 1. 一个Target中的类无法直接在另外1个Target中访问. 2. 类的属性代表什么? a. 类的属性代表这类事物具有的共同的特征 b. 类的属性代表这个类所拥有的东西. 灯: 属性: 形状 功率 价格  品牌 剩余寿命 方法: 照明. 音响: 方法: 发声音. 门: 属性: 尺寸 材料 颜色 价格 方法: 开 关 3. 类的方法代表什么? a. 代表这个类所具备的行为. 这个类所具备的功能. b. 一个类有什么方法 就去分析这个类有什么功能. 4. 属性的本质是变量.

python类对象属性查找原理

class Foo(object): def __init__(self): # 这是一个对象属性 self.obj_pro = 12 # 这是一类属性 c_pro = 11 # 这是一个静态方法 @classmethod def c_method(self): print('c_method') if __name__ == '__main__': f = Foo() """ 如何查找对象属性? 就是在对象的__dict__字典去找,对象__dict__找不到,再去类__d

iOS的Runtime机制下给类别(category)添加属性、替换原有类的方法执行

一.Runtime的理解 OC是面向对象的语言这是常识,其实就是通过Runtime机制动态创建类和对象,这里只是简单的运用runtime的使用! 二.类别(category)添加属性_使用前记得导入头文件#import <objc/runtime.h> 通过这三个方法动态的绑定属性 OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy poli

java类中属性的加载顺序,以及内存分配情况介绍

看下面例子及说明: /** 假如有外部类调用了该类,代码为:new StaticTest(); 那么下面是类属性的加载顺序 */ public class StaticTest{ public int dsd=2;//第3 //多个对象会有多次分配内存 public awds() { int sdsfsd=2;//第4 //多个对象会有多次分配内存 } //静态代码块 static{ System.out.println("静态代码块正在加载...");//第1 } public st

object-c计划tips-添加到类对象属性

这个问题从网络包的内容,由于保密问题,我刚才所描述我的业余的想法. 基本的想法: 网络请求,我们应该能够使用基类BaseNetWork, 然后由派生类继承BaseNetWork,并实现一些特殊的方法. 一般标准的流程是传入block, 当网络请求完成后.通过block回调回来.这里叙述的关键不是怎样实现一个网络请求和回调block的相关内容,而是怎样取消请求. 一般基类会实现一个cancelNetWork方法.它依据自己的url进行cancel操作. 举例: 我们使用 DerivedNetWor

利用runtime实现延展动态改变模型类中属性的set,get方法

昨天大概的阐述了一下关于构架控制容器的概念,但是如果要丰满这个想法还有很多问题,比如如果我想对一些controller进行管理就势必涉及到controller的加载以及缓存,而想做这些的前提就是构建一个controller表.对表中设定的字符串管理,从而管理对应的controller.传统创建表的方法有很多,最为常用的就是plist文件,但是对于iOS开发的程序员来说,如果这个plist写死,在管理的时候就会比较死板,要知道oc是一门灵活的,动态的语言.如果我们使用NSUserDefaults,

ios 中Category类别(扩展类)专题总结

原创地址   http://www.code4blog.com/archives/294 类别 类别是一种为现有的类添加新方法的方式. 利用Objective-C的动态运行时分配机制,可以为现有的类添加新方法,这种为现有的类添加新方法的方式称为类别catagory,他可以为任何类添加新的方法,包括那些没有源代码的类. 类别使得无需创建对象类的子类就能完成同样的工作 一.创建类别 1.声明类别 声明类别与声明类的形式很相似 @interface  NSString(NumberConvenienc

python3 类的属性、方法、封装、继承及小实例

Python 类 Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法. 对象可以包含任意数量和类型的数据. python类与c++类相似,提供了类的封装,继承.多继承,构造函数.析构函数. 在python3中,所有类最顶层父类都是object类,与java类似,如果定义类的时候没有写出父类,则object类就是其直接父类. 类定义 类定义语法格式如下: class ClassName:    <statem

Java编程里的类和对象

像我们搞计算机这块的,都知道这么一件事,当前的计算机编程语言主要分为两大块,一为面向过程,二为面向对象.Java就是一门纯面向对象的语言.学习了一个月左右的Java,在下对于Java当中的类和对象有了基本的认识.接下来我就来谈谈自己的看法,各位大神勿喷,新手小白敬上. 既然谈到类和对象,首先,我们要明确一个概念.那就是,什么叫类?什么是对象? 首先让我们来谈谈什么叫类.类是一个比较抽象的概念,如何给它定义,是一个难题.我们通常这样称呼它,模板.是的,它代表了具有相同属性.行为等的一种事物.就比如