2

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

除了“非原子”和“原子”之外,我无法找到实际的表示。

对于具有不同属性属性(例如强/弱、复制/分配和 __unsafe_unretained)的 getter 和 setter,实际代码是什么样的?

4

1 回答 1

0

您可以在objc4 github repo中查看源代码

吸气剂: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);
}

设置器: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 没有任何代码。编译器可以简单地分配指针而无需其他任何东西。

于 2016-10-12T09:50:56.153 回答