Посмотреть контроллер / управление памятью - PullRequest
2 голосов
/ 22 июня 2011

Я немного запутался с управлением памятью в контроллерах представления.

Допустим, у меня есть такой заголовочный файл:

@interface MyController : UIViewController {
    NSMutableArray  *data;
}
@property (nonatomic, retain) NSMutableArray *data;
@end

и .m файл выглядит так:

@implementation MyController
@synthesize data;

- (void)dealloc
{
    [self.data release];
    [super dealloc];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    if (self.data == nil)
        self.data = [[NSMutableArray alloc] init];
}

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

Это нормально с точки зрения правильного управления памятью? Будет ли это работать после Deloloc через Memory Warning? Как вы делаете это в своих приложениях?

Спасибо за ваши ответы;)

Ответы [ 3 ]

1 голос
/ 22 июня 2011

Вам не гарантируется, что viewDidUnload когда-либо будут вызваны. В отличие от init / dealloc, который вызывается парами, viewDidUnload вызывается неопределенно. viewDidUnload вызывается только в случае нехватки памяти и ваш вид не является активным.

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

viewDidUnload должен содержать только очистку ваших IBOutlet s и удаление легко восстанавливаемых данных.

1 голос
/ 22 июня 2011

Эти строки из -viewDidUnload оба выпуска data:

[self.data release];
self.data = nil;

Поскольку вы используете установщик свойств во второй строке, а data является сохраняемым свойством, установщик выдаст data. Это избыточный выпуск, и он вызовет сбой сразу или позже, в зависимости от того, сохранят ли этот объект другие объекты. Чтобы исправить, просто удалите первую строку и положитесь на установщик, чтобы сделать правильную вещь.

Метод -dealloc, с другой стороны, не должен использовать сеттер, как сейчас. Вам следует изменить:

[self.data release];

до:

[data release];
data = nil;       // this line isn't strictly necessary, but often considered good form

Причина в том, что вполне возможно, что этот класс может быть разделен на подклассы, и кто-то может переопределить установщик свойств таким образом, что у него есть некоторые побочные эффекты, которые могут вызвать проблемы, когда объект освобождается. Вы должны получить доступ к ивару напрямую - обратите внимание, что я остановился на «я». так что мы имеем дело с ivar, а не с accessor. (-init и -dealloc - единственные места, где вам нужно беспокоиться об этом; используйте средства доступа к свойствам везде.)

1 голос
/ 22 июня 2011

Несмотря на то, что alloc-retain вызывает баланс в viewDidLoad и viewDidUnload и не должно вызывать проблем с памятью, было бы чётко получить право владения только один раз и отказаться от него один раз, а не дважды.

- (void)viewDidLoad
{
    [super viewDidLoad];

    if (self.data == nil)
        self.data = [NSMutableArray array];
}

и

- (void)viewDidUnload
{
    [super viewDidUnload];

    self.data = nil;
}
...