非arc Objective-C属性访问器是什么样的?



作为学习内存管理概念的一部分,我想知道Objective-C属性的getter和setter是如何实现的。

除了"nonatomic"one_answers"atomic"之外,我还没有找到一个实际的表示。

对于具有不同属性属性(如strong/weak, copy/assign和__unsafe_unretained)的getter和setter,实际代码是什么样子的?

你可以在objc4 github repo查看源代码

getter: https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-accessors.mm L48

id objc_getProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic) {
    if (offset == 0) {
        return object_getClass(self);
    }
    // Retain release world
    id *slot = (id*) ((char*)self + offset);
    if (!atomic) return *slot;
    // Atomic retain release world
    spinlock_t& slotlock = PropertyLocks[slot];
    slotlock.lock();
    id value = objc_retain(*slot);
    slotlock.unlock();
    // for performance, we (safely) issue the autorelease OUTSIDE of the spinlock.
    return objc_autoreleaseReturnValue(value);
}

setter: https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-accessors.mm L70

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);
}

加载弱变量:https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/NSObject.mm#L444

id
objc_loadWeakRetained(id *location)
{
    id result;
    SideTable *table;
 retry:
    result = *location;
    if (!result) return nil;
    table = &SideTables()[result];
    table->lock();
    if (*location != result) {
        table->unlock();
        goto retry;
    }
    result = weak_read_no_lock(&table->weak_table, location);
    table->unlock();
    return result;
}

我不认为unsafe_retained有任何代码。编译器可以简单地赋值指针,而不需要其他任何东西。

最新更新