Каковы плюсы и минусы этих различных стратегий деаллока? - PullRequest
2 голосов
/ 06 мая 2011

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

Я надеюсь получить сводную информацию о плюсах и минусах, которые позволят мне и другим легко выбрать подход по умолчанию, но при этом понять, когда делать исключения.Вот 3 варианта, которые я видел:

Предположим, @property (nonatomic, retain) MyObject *foo;

// Release-only. Seems to be the favored approach in Apple's sample code.
- (void)dealloc {
    [foo release];
    [super dealloc];
}

// Property accessor set to nil.
- (void)dealloc {
    self.foo = nil;
    [super dealloc];
}

// Release, then nil.
- (void)dealloc {
    [foo release];
    foo = nil;
    [super dealloc];
}

Если вам нужно добавить другой вариант, прокомментируйте здесь, и я отредактирую оп

1 Ответ

2 голосов
/ 08 мая 2011

Версии (1): лучший.У каждого из остальных есть атрибуты, которые могут быть вредными.

Версия (2): Обычно рекомендуется не использовать средства доступа в dealloc (или init).Причиной этого является то, что объект находится в процессе разрушения (или создания) и находится в противоречивом состоянии.Это особенно верно, если вы пишете библиотеку, где кто-то другой может позже переопределить метод доступа, не подозревая, что он может быть вызван, когда объект находится в несовместимом состоянии.(Конечно, даже Apple иногда нарушает это правило -[UIView initWithFrame:], вызывает -[UIView setFrame:], если аргумент не является CGRectZero, что может быть полезно для отладки.

Version (3); Установка ivar на nil служитбесполезная цель, на самом деле это может маскировать ошибку и затруднить отладку more . Чтобы понять, почему это так, рассмотрим следующий фрагмент кода, предположим, что myObject имеет версию (3) dealloc.

FastMovingTrain* train = [[FastMoving alloc] init];
MyObject* myObject = [[MyObject alloc] init];
myObject.foo = train;
[train release];
// my myObject.foo is the only thing retaining train
...

....
[myObject release];

// Because of version (3) dealloc if myObject
// points to the dealloced memory this line 
// will silently fail... 
[myObject.foo applyBrakes];

Интересно, что этот код предоставляет возможность продемонстрировать, когда установка переменной nil после того, как release имеет смысл. Код можно сделать более устойчивым, изменив его следующим образом.

FastMovingTrain* train = [[FastMoving alloc] init];
MyObject* myObject = [[MyObject alloc] init];
myObject.foo = train;
[train release];
// my myObject.foo is the only thing retaining train
...

....
[myObject release];
myObject = nil;

// This assertion will fail.
NSAssert(myObject, @"myObject must not be nil");
[myObject.foo applyBrakes];

Просто мои 0,02 доллара.

...