Установите в ноль в viewDidUnload, но отпустите в dealloc - PullRequest
10 голосов
/ 21 апреля 2011

Я читал весь день о том, почему представления должны быть установлены в nil в viewDidUnload и выпущены в dealloc. Все статьи повторяют одно и то же. Да, я знаю, что закулисные инструкции отличаются, но каковы практические различия?

var = nil

  1. Если var является сохраненной собственностью, вернуть память старому объекту var, на которую указывал.
  2. Установите переменную на ноль.

[вар релиз]

  1. Восстановить память var указывает на.
  2. var теперь указывает на ничто, что эквивалентно nil

Для меня оба способа восстановления памяти имеют один и тот же конечный результат. Так почему же один над другим? Каждая книга там говорит мне, чтобы установить в ноль в viewDidUnload и выпустить в dealloc. Кто-то должен указать на плохие вещи, которые могут произойти, если представление было выпущено в viewDidUnload и обнулено в dealloc.

.h

#import <UIKit/UIKit.h>
@interface DisclosureDetailController : UIViewController {
 UILabel* label;
}
@property (nonatomic, retain) IBOutlet UILabel* label;
@end

.m

#import "DisclosureDetailController.h"
@implementation DisclosureDetailController
@synthesize label;
- (void)viewDidUnload {
 self.label = nil;
 // OR [self.label release];
 [super viewDidUnload];
}
- (void)dealloc {
 [self.label release];
 // OR self.label = nil;
}

Ответы [ 2 ]

25 голосов
/ 21 апреля 2011

Перво-наперво, строка

[self.label release];

абсолютно неверна независимо от того, где вы ее называете.Вы должны никогда звонить -release по результатам доступа к собственности.Это точно так же, как и написание [[self label] release], которое, я надеюсь, вы можете распознать как неправильное.

Пример кода должен выглядеть следующим образом:

- (void)viewDidUnload {
    self.label = nil;
    [super viewDidUnload];
}
- (void)dealloc {
    [label release];
    [super dealloc];
}

Если мы посмотрим на -viewDidUnload Во-первых, это довольно просто.self.label = nil; правильно.Точно так же правильно будет [self setLabel:nil];.И хотя это не так хорошо, было бы приемлемо написать [label release], label = nil;.Эта последняя форма не так хороша, потому что она обходит метод setter, который может делать больше вещей, чем просто освобождение свойства (например, он может поддерживать внутреннее состояние, которое заботится о значении свойства).Он также обходит уведомления KVO.

Реальный вопрос здесь в том, что вы делаете в -dealloc.Многие люди полагают, что говорить «1020» совершенно нормально, и, практически говоря, это будет работать большую часть времени.Проблема в том, что в остальное время это приведет к незначительным ошибкам.Есть две вещи, которые может сделать вызывающий сеттер.Во-первых, это может вызвать побочные эффекты в вашем классе, если метод setter реализован вручную (даже если вы не реализуете setter самостоятельно, подкласс может это сделать).Во-вторых, он может транслировать уведомления KVO.Ни одна из этих вещей не желательна, когда вы находитесь в -dealloc.Выпуская ivar напрямую, как в [label release];, вы избегаете как потенциальных побочных эффектов, так и уведомлений KVO.

4 голосов
/ 21 апреля 2011

практические различия заключаются в следующем.

Установка свойства равным nil с помощью метода доступа к свойству позволит синтезированному методу завладеть вашим новым свойством nil после освобождения существующего свойства.

// we will take for granted that you synthesize this property
@property (nonatomic, retain) IBOutlet UILabel* label;

мы будем использовать средство доступа к свойству и установить его равным nil.

//This will in actuality set the new value of nil to the label variable after
//releasing the existing label that it had a retain count on.
self.label = nil; 

затем мы выпустим его напрямую

//This line on the other hand will merely release the label directly. 
//As soon as the label is deallocated you will have a handle to an invalid object. 
//(memory space that used to be your label)
[label release];

Теперь мы покажем упрощенную версию средства доступа к свойству,(не использовать буквально)

//Simply put the following is an pseudo equivalent of the property setter.
[label release]
label = nil;

главное здесь то, что средство доступа к свойству обрабатывает освобождение метки, которую оно сохранило.и установив его на то, что вы вручаете (в данном случае это ноль)

, поэтому добавление следующего кода

label = nil;

без освобождения сохраненного объекта вызовет утечку памяти, и вы получитесохранить счет на ярлыке, на который у вас больше нет указателя.

Примечание :

Еще одна вещь, которую необходимо учитывать.Любой указатель, который равен нулю.сможет принимать сообщения.И в ответ они ответят нулем.С другой стороны, объект, который был освобожден, как только эта память будет освобождена, ваше сообщение к нему, скорее всего, выдаст ошибку.результат непредсказуем.Это хорошая причина для установки ваших свойств на ноль.Мало того, что это будет обращаться с выпуском для объекта, который это держит.но это также даст вам объект, на который вы можете безопасно послать сообщение, не взорвавшись.

Хорошая точка @ WaltSellers

Доступ к переменной - независимо от того,это средство доступа к свойству или переменная экземпляра.- После того, как он был выпущен полностью.Приведет к "неопределенным" действиям.Это означает, что доступ может работать нормально, или он может испортить другие части приложения, или, наоборот, он может просто взорваться очень быстро и завершить работу приложения-нарушителя.В основном, установив для переменной значение nil после освобождения, вы сможете обойти эту ошибку.

Отдельный совет от меня

, чтобы преодолеть неправильное представление метода доступа к свойству и переменной экземпляра.Я просто @synthesize и говорю ему установить имя переменной.

@synthesize label = _label;

, делая это, позволяет мне отличать self.label от его переменной экземпляра.так как вы больше не можете получить доступ к переменной метки напрямую без предшествующего _

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...