Основное управление памятью iPhone - PullRequest
1 голос
/ 27 июля 2010

Это правильное управление памятью?Что мне интересно, так это если я должен release после alloc в -viewDidLoad.

SomeViewController.h

#import <UIKit/UIKit.h>

@interface SomeViewController : UIViewController {
    UIButton *someButton;
    NSString *someString;
}

@property (nonatomic, retain) IBOutlet UIButton *someButton;
@property (nonatomic, copy) NSString *someString;

@end

SomeViewController.m

#import "SomeViewController.h"

@implementation SomeViewController

@synthesize someButton, someString;

- (void)viewDidLoad {
    [super viewDidLoad];
    someButton = [[UIButton alloc] init];
    someString = [[NSString alloc] init];
}

- (void)viewDidUnload {
    self.someButton = nil;
    self.someString = nil;
}

- (void)dealloc {
    [someButton release], self.someButton = nil; 
    [someString release], self.someString = nil;
    [super dealloc];
}

@end

Спасибо

Редактировать: еще одна вещь.Если я поставлю UIButton в IB, мне все еще нужно alloc это?

Ответы [ 3 ]

4 голосов
/ 27 июля 2010

Это довольно длинная история, которую вы можете найти, погугливая, и кто-то может войти сюда, но для краткости вот несколько хитростей:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.someButton = [[[UIButton alloc] init] autorelease];
    self.someString = [[[NSString alloc] init] autorelease];
}

Т.е. используйте сеттеры (self.something = ...;) и всегда либо release, либо autorelease любой alloc, который вы делаете.(Логическим различием было бы то, кто «владеет» объектами; с этими настройками функция отказывается от владения, и класс получает его.)

edit: no, если вы создаете кнопку вIB, кнопка просто будет там, выделена и инициализирована с вашими стилями.

2 голосов
/ 27 июля 2010

Когда вы вызываете init для объекта, счетчик сохранения становится равным 1. У вас есть два разных атрибута установщика: один «сохраняет» для вашей кнопки UIB, а другой «копирует» для вашей строки NSString.Когда вы вызываете

self.someButton = someUIButtonObject;

someUIButtonObject получает сообщение сохранения, и поэтому его счетчик сохранения увеличивается до 1. В случае вашего исходного кода вызов release в dealloc выпустит одну ссылку на someUIButtonObject, но все равно будетиметь счет сохранения 1 и, таким образом, будет утечка.

В другом случае с вашей строкой NSSt существует другая проблема, но все же происходит утечка памяти.Здесь ваш вызов [[NSString alloc] init] приводит к новому строковому объекту, а затем вызов

self.someString = someNSStringObject;

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

Небольшое примечание: я не знаю, как выглядит ваш реальный код, но не забывайте, что строки NSSt неизменяемы (так что простой вызов [[NSString alloc] init] довольно бесполезен) и UIButton нужныфрейм (попробуйте [[UIButton alloc] initWithFrame: (CGRect) frame];).

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

self.someButton = [[[UIButton alloc] init] autorelease];

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

UIButton* tempButton = [[UIButton alloc] init];
self.someButton = tempButton;
[tempButton release];

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

Кроме того, всегда используйте средства получения / установки для доступа к этимсвойства (self.someButton в отличие от someButton).Таким образом, вы случайно не назначаете someButton новому указателю и не теряете старый.

Когда вы создаете кнопку в IB, XIB содержит ссылку на кнопку (+1 сохраняет счет).Если вы создаете IBOutlet, чтобы получить программный доступ к кнопке, вы получаете еще одно сохранение для объекта, поэтому, если у вас есть IBOutlet для someButton, someButton имеет счет сохранения 2, как только загружается XIB.Вам не нужно выделять объект, это делается автоматически при загрузке XIB в память.Кроме того, вы несете ответственность только за выпуск одной ссылки на кнопку (ваша ссылка на IBOutlet).Как правило, рекомендуется опубликовать ссылку, как только вы узнаете, что она вам больше не нужна.Например, если вы знаете, что вам нужна кнопка, и вам нужно выполнить начальную настройку, и ничего больше, то вы, вероятно, сделаете что-то вроде этого:

-(void)viewDidLoad {
  // Do some customization of someButton
  [someButton release];
}

В противном случае вы, вероятно, выпустите someButton в viewDidUnload, посколькув этот момент вам больше не понадобится ссылка на кнопку.

0 голосов
/ 28 июля 2010

Если ваша кнопка установлена ​​в IB, вам не нужно выделять ее в коде (IB делает это за вас).

По сути, каждый объект, который вы создали с помощью alloc или new, должен иметь release где-то в вашем коде.Если это переменная интерфейса, вы должны освободить их в функции dealloc.

...