#runtime源码笔记#

property有哪些修饰符,它们的实现原理是什么

首先回答题目的问题,property的修饰符有nonatomic、copy、strong、weak、assign、unsafe_unretained、readonly、getter。
对于给property设置值的runtime源码,在objc_accessors.mm文件中实现。通过看源码,我们看到里面有几个长得非常像的函数,它们都是以objc_setProperty_##开头的,意思就非常明确了,property修饰符是通过组合的方式去用的,这里的函数也就是对应于组合修饰符的实现。它分别有以下几种组合:

1、objc_setProperty_atomic()
2、objc_setProperty_nonatomic()
3、objc_setProperty_atomic_copy()
4、objc_setProperty_nonatomic_copy()

而这几个函数的内部都是调用reallySetProperty()函数实现最终的逻辑的。我们再看看reallySetProperty的源码:

static inline void reallySetProperty(id self, SEL _cmd, id newValue, ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
    if (offset == 0) {
        object_setClass(self, newValue);
        return;
    }

    id oldValue;
    id *slot = (id*) ((char*)self + offset);

    if (copy) {
        newValue = [newValue copyWithZone:nil];
    } else if (mutableCopy) {
        newValue = [newValue mutableCopyWithZone:nil];
    } else {
        if (*slot == newValue) return;
        newValue = objc_retain(newValue);
    }

    if (!atomic) {
        oldValue = *slot;
        *slot = newValue;
    } else {
        spinlock_t& slotlock = PropertyLocks[slot];
        slotlock.lock();
        oldValue = *slot;
        *slot = newValue;        
        slotlock.unlock();
    }

    objc_release(oldValue);
}

解读总结一下这段源码,如果copy为true,则调用copyWithZone:,而property修饰符中是没有mutableCopy的,所以默认的setter方法中的复制都是不可变复制。如果是atomic修饰的,它赋值前会进行加锁处理。另外对于id类型的strong,内部实现是调用NSObject.mm中的objc_storeStrong()。非id类型的是retain新值,release旧值。objc_storeStrong()的内部实现也是retain新值,release旧值。而对于有weak修饰的property,其内部实现是通过调用objc_storeWeak()实现的。对于weak的实现,后续单独讲。

weak、assign、unsafe_unretained的区别是什么,它们是如何实现的

这三个修饰符的功能有点类似,都是修饰非拥有管理权(strong为拥有对象管理权),不同的是weak在对象释放后会被置为nil,而asssign和unsafe_unretained并不会,他们的实现很简单,就是简单的赋值,所以后两者会导致野指针,另外weak在property中的实现是通过 objc_storeWeak ()实现的,在NSObject.mm中可以看到具体的实现。
简单的说就是runtime定义一个weak表,这个表维护了一个对应关系,就是用被weak指向的对象的内存地址作为key,所有指向这个对象的weak指针数组作为value。

你可能感兴趣的:(#runtime源码笔记#)