У меня есть некоторые вопросы о синтезированных свойствах в Objective-C. Полный список следует, но основной вопрос заключается в следующем: Как компилятор гарантирует, что ivars для синтезированных свойств будут правильно выпущены, хотя мой код может включать или не включать методы выпуска в dealloc?
Примечание. Я решил не публиковать их как отдельные вопросы, потому что они настолько тесно связаны и потому что есть несколько существующих вопросов, которые затрагивают отдельные проблемы, не вникая в суть дела.
Несколько похожих вопросов:
- Требуется ли сохранить свойство?
- Какая разница между свойством и синтезом?
- Вопрос о сохранении атрибута с собственностью и синтезе
Настройка: Рассмотрим класс с единственным свойством:
@interface Person : NSObject
{
NSString * name;
}
@property (nonatomic, retain) name;
@end
Вопрос №1: Самый простой случай:
@implementation Person
@synthesize name;
@end
При этой настройке я предполагаю, что name
будет автоматически выпущен, когда будет выпущен объект 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
?