Правильно переопределить сеттер в Objective-C
Я просто попытался переопределить стандартные синтезированные сеттеры свойства. Пока все в порядке, я просто установил ivar на свое новое значение. Но потом я спросил себя: "Что происходит с сохранением количества сохраненных свойств"... Я не нашел хорошего ответа, который объяснил это мне. Поэтому я прошу об этом здесь. Есть ли что-нибудь, о чем я должен знать, если я переопределяю установщик свойств, который установлен в retain
, и как я могу сделать это правильно? Я не использую ARC.
Вот пример:
@property(nonatomic)NSInteger number;
- (void)setNumber:(NSInteger)number {
_number = number; // This should be fine, since it no retained object I want to set
}
@property(nonatomic, retain)NSObject *something;
- (void)setSomething:(NSObject *)something {
_something = something; // This is not fine. As far as I know you should never do sth. like this... But how do I set it correctly?
}
Ответы
Ответ 1
-(void) setAnObject:(NSObject*) someObject {
if (_anObject != someObject) {
NSObject* savedObject = _anObject;
_anObject = [someObject retain];
[savedObject release];
}
}
Если вы отпустите старый указатель перед сохранением нового, вы можете иметь ситуацию, когда вы устанавливаете значение из значения в старом объекте, а выпуск старого объекта заставляет новый объект идти POOF! незадолго до его сохранения.
В качестве альтернативы вы можете сделать
....
[someObject retain];
[_anObject release];
_anObject = someObject;
...
Ответ 2
Вы переписываете сеттеры только для другого имени? Если это можно сделать, изменив определение свойства:
@property(nonatomic, setter = nameOfSetter: )NSInteger number;
То же самое работает для getter.
Ответ 3
Отредактировано после изучения принятого ответа от Hot Licks
объявление свойства и синтез x
@property (nonatomic, retain) ClassX x;
@synthesize x = _x;
перегруженный сеттер для x
- (void)setX:(ClassX *)x;
{
if (x != _x)
{
[x retain];
[_x release];
_x = x;
// custom code here
}
}
Ответ 4
- (void) setSomething:(NSObject*) something
{
if (something != _something)
{
[_something release];
_something = [something retain];
}
}
Вам нужен оператор if
, потому что в противном случае, если что-то и что-то было уже одно и то же, вы бы перевыполнили объект, возможно, он исчезли и возникли проблемы.