Как выпуск обрабатывается для @synthesized, сохраняют свойства?

У меня есть некоторые вопросы о синтезируемых свойствах в Objective C. Полный список следует, но основной вопрос - это: Как компилятор гарантирует, что ivars для синтезируемых свойств правильно выпущены, даже при том, что мой код может или не может включать методы выпуска в dealloc?

Примечание: Я решил не отправить их как отдельные вопросы, потому что они так тесно связаны и потому что существует горстка существующих вопросов, которые затрагивают отдельные проблемы, действительно не добираясь до сути дела.

Несколько подобные вопросы:


Установка: Рассмотрите класс с единственным свойством:

@interface Person : NSObject
{
    NSString * name;
}
@property (nonatomic, retain) name;
@end

Вопрос № 1: очень простой случай:

@implementation Person
@synthesize name;
@end

С этой установкой я принимаю это name будет автоматически выпущен каждый раз, когда a Person объект выпущен. В моем уме компилятор просто вставляет [name release] в dealloc метод, как будто я ввел его сам. Это корректно?


Вопрос № 2: Если я принимаю решение записать свое собственное dealloc метод для этого класса, и я опускаю вызов к [name release], это протечет?

@implementation Person
@synthesize name;
- (void)dealloc { [super dealloc]; }
@end

Вопрос № 3: Если я принимаю решение записать свое собственное dealloc метод для этого класса, и я включаю вызов в [name release], будет тот результат в двойном выпуске с тех пор @synthesize уже заботился о нем для меня?

@implementation Person
@synthesize name;
- (void)dealloc { [name release]; [super dealloc]; }
@end

Вопрос № 4: Если я принимаю решение записать свое собственное средство доступа свойства для этого класса, но я не пишу свое собственное dealloc метод, будет name быть пропущенными?

@implementation Person
@dynamic name;
- (void)setName:(NSString *)newName
{
    [newName retain];
    [name release];
    name = newName;
}
@end

Вопрос № 5: у Меня есть чувство (на основе опыта), что ни один из вышеупомянутых сценариев не приведет к утечкам или двойным выпускам, так как язык был разработан для предотвращения их. Это, конечно, поднимает вопрос "как?". Компилятор просто достаточно умен для отслеживания каждый возможный случай? Что, если я должен был сделать следующее (отмечают, что это - смехотворный пример, просто означало иллюстрировать мой тезис):

void Cleanup(id object) { [object release]; }

@implementation Person
@synthesize name;
- (void)dealloc { Cleanup(name); }
@end

Был бы тот дурак компилятор в добавление другого [name release] к dealloc метод?

65
задан Community 23 May 2017 в 12:06
поделиться

2 ответа

Q1:

Нет. @synthesize не изменяет -dealloc за вас. Вы должны -выпустить имя самостоятельно.

Q2:

Да, утечка будет. По той же причине, что и Q1.

Q3:

Нет, это не будет двойного релиза. По той же причине, что и Q1.

Q4:

Да, утечка будет. По той же причине, что и Q1.

Q5:

Нет, это не будет двойного выпуска. По той же причине, что и Q1.


Вы можете проверить это самостоятельно, переопределив -retain и -release и -dealloc , чтобы сообщить о том, что происходит.

#import <Foundation/Foundation.h>

@interface X : NSObject {}
@end
@implementation X
-(oneway void)release {
        NSLog(@"Releasing %p, next count = %d", self, [self retainCount]-1);
        [super release];
}
-(id)retain {
        NSLog(@"Retaining %p, next count = %d", self, [self retainCount]+1);
        return [super retain];
}
-(void)dealloc {
        NSLog(@"Dealloc %p", self);
        [super dealloc];
}
@end

@interface Y : NSObject {
        X* x;
}
@property (nonatomic, retain) X* x;
@end
@implementation Y
@synthesize x;
- (void)dealloc { [x release]; [super dealloc]; }
@end

int main () {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        Y* y = [[Y alloc] init];
        X* x = [[X alloc] init];
        y.x = x;
        [y release];
        [x release];
        [pool drain];                                                    
        return 0;
}

В Q1, Q2 и Q4 последний -retainCount из x равен 1, поэтому есть утечка, а в Q3 и Q5 последний -retainCount равен 0 и вызывается -dealloc , поэтому утечки нет.

57
ответ дан 24 November 2019 в 15:30
поделиться

Из документации Objective-C по свойствам :

dealloc

Объявленные свойства в основном принимают место объявления метода доступа ; когда вы синтезируете свойство , компилятор создает только любые отсутствующие методы доступа. Нет прямого взаимодействия с методом dealloc - свойства не автоматически освобождаются для вас. Однако объявленные свойства предоставляют полезный способ перекрестной проверки реализации вашего метода dealloc : вы можете найти все объявления свойств в файле заголовка и убедиться, что Свойства объекта , не отмеченные как присвоение, освобождаются, а те, которые отмечены как присвоение, не освобождаются.

Это, по сути, ответ на все ваши вопросы.

17
ответ дан 24 November 2019 в 15:30
поделиться