Как выглядят средства доступа к свойствам, не относящимся к ARC Objective-C?

Я хочу знать, как геттер и сеттер для свойства Objective-C реализуются как часть изучения концепции управления памятью.

Мне не удалось найти фактическое представление, отличное от «неатомного» и «атомного».

Как выглядит реальный код для геттеров и сеттеров с разными атрибутами свойств, такими как strong/weak, copy/assign и __unsafe_unretained?


person NSUser    schedule 12.10.2016    source источник
comment
Не-ARC в названии и сильный/слабый в вопросе являются взаимоисключающими.   -  person Droppy    schedule 12.10.2016
comment
github.com/opensource-apple/objc4/blob/   -  person Bryan Chen    schedule 12.10.2016
comment
@Droppy Мне просто интересно узнать об их внутренней реализации. независимо от ARC или MRC.   -  person NSUser    schedule 12.10.2016
comment
Ну, вы должны понимать, что с ARC компилятор делает тяжелую работу за кулисами, и никто не хочет внимательно на это смотреть (кроме разработчиков и серьезно любопытствующих). Однако есть много примеров версий без ARC, в том числе многие на этом сайте.   -  person Droppy    schedule 12.10.2016
comment
@ Капля, да, ты прав. Я только что видел сеттер strong - -(void)setName:(NSString *)name{ [name retain]; [_name release]; _name = name; } в нем так много концепций, например, почему [name retain] первая строка. Поэтому я просто хотел увидеть реальную реализацию. Я никогда не работал в МРЦ. вот почему некоторое время я чувствую некоторые проблемы, понимая это. вот почему я теперь понимаю каждую вещь до конца.   -  person NSUser    schedule 12.10.2016
comment
Вам нужны настоящие синтезированные определения или как они выглядели бы, если бы вы реализовали их вручную?   -  person jscs    schedule 12.10.2016


Ответы (1)


Вы можете проверить исходный код в репозитории objc4 github.

геттер: 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. Компилятор может просто присвоить указатель и ничего больше.

person Bryan Chen    schedule 12.10.2016