Могу ли я пропустить создание отдельного указателя при настройке моего viewController? - PullRequest
4 голосов
/ 06 мая 2011

Почему мне нужно создать указатель только для того, чтобы выделить память, а затем немедленно ее освободить?

Другими словами, я не могу просто сделать это:

self.viewController = [[HelloWorldViewController alloc] initWithNibName:@"HelloWorldViewController" bundle:[NSBundle mainBundle]];

вместоthis:

HelloWorldViewController *newViewController = [[HelloWorldViewController alloc] initWithNibName:@"HelloWorldViewController" bundle:[NSBundle mainBundle]];
self.viewController = newViewController;
[newViewController release];

[EDIT]

Чтобы предоставить более широкий контекст по моему вопросу: (в рамках @implementation @interface HelloWorldAppDelegate: NSObject )

@synthesize window=_window;
@synthesize viewController=_viewController;

...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    HelloWorldViewController *newViewController = [[HelloWorldViewController alloc] initWithNibName:@"HelloWorldViewController" bundle:[NSBundle mainBundle]];
    self.viewController = newViewController;
    [newViewController release];

    self.window.rootViewController = self.viewController;

    [self.window makeKeyAndVisible];
    return YES;
}

...

- (void)dealloc
{
    [_window release];
    [_viewController release];
    [super dealloc];
}

Так что, в методе didFinish ..., могу ли я использовать короткую версию, которую я поставил выше, или произойдет утечка?

[ВТОРОЕ РЕДАКТИРОВАНИЕ]

Кажется, я просто не могу дать достаточно информации.Я всегда не решаюсь выкладывать огромную кучу кода.У меня есть это в HelloWorldAppDelegate.h:

@property (nonatomic, retain) IBOutlet HelloWorldViewController *viewController;

Итак, поправьте меня, если я ошибаюсь.Учитывая объявление viewController в заголовочном файле, если я использую метод ярлыка (в первом фрагменте кода выше), программа утечет.Счетчик объекта увеличивается один раз на alloc, а затем второй раз на retain, а затем уменьшается на один раз для освобождения, создавая сеть +1 на счетчике ссылок указателя.

Ответы [ 2 ]

3 голосов
/ 06 мая 2011

Вы делайте должны освободить объект, который вы выделили, иначе вы получите утечку памяти. Присвоение self.viewController (предположительно) сохраняет вновь выделенную HelloWorldViewController, поэтому у вас есть две «претензии» на объект - одна от вашего вызова к alloc и одна от retain, но вы на самом деле вы больше не собираетесь его использовать под именем newViewController, поэтому вы отказываетесь от этой конкретной претензии, позвонив release.

«Длинная» форма, использующая переменную temp, фактически является правильным способом сделать это. Отправка release в результат доступа к свойству: [self.viewController release]; сразу после его установки вполне может сработать, но неверен (и сгенерирует предупреждение компилятора для последних версий LLVM).

Также возможно сделать это:

self.viewController = [[[HelloWorldViewController alloc] initWithNibName:@"HelloWorldViewController" 
                                                                  bundle:[NSBundle mainBundle]]
                          autorelease];

, который говорит: «Я создал эту вещь, чтобы использовать ее кратко, но она мне не понадобится вне этого стека немедленных вызовов, так что давай, отпустим ее для меня позже».

Если viewController не является retain ING собственности, то все это спорный вопрос, и вы не должны отправлять release в новый контроллер представления, потому что он будет освобождаться прежде чем вы сможете использовать его.

ОБНОВЛЕНИЕ: Ваш расширенный вопрос ничего не меняет *. Если вы не отправите release до того, как newViewController выйдет из области видимости, вы получите утечку. ** Это работает так: любой объект (A, B, C), которому нужно использовать объект X, и поэтому заботится о его сохранности, отправляет retain X. Когда вы alloc объект, предполагается, что вам нужно его использовать. Когда любому из A, B или C больше не нужен X, он отправляет release в X, тем самым говоря: «X может быть освобожден, и это не повлияет на меня». Вам необходимо сбалансировать количество выдвигаемых вами претензий (используя retain, alloc, copy / mutableCopy или new) на объекте с количеством отказов, которые вы сделали (отправив release или autorelease) или у вас на руках будет утечка или случайное освобождение.

Сейчас я дам вам ссылку на документы, но не расстраивайтесь, это всего лишь одна страница, которую вам нужно прочитать и усвоить: Основное правило управления памятью какао .


* На самом деле, вы пропустили единственную часть, которая могла изменить ответ, а именно ваш

@property () HelloWorldViewController * viewController;

декларация. Если в этих скобках указано «сохранить», то при установке этого свойства делегат приложения отправляет переданный объект retain. Если он говорит «назначить» или круглые скобки отсутствуют, то, как я сказал, вы не должны отправлять release этому объекту.

** Примечание для любых наблюдающих педантов: вы можете, конечно, отправить release дважды на viewController в некоторый момент, но это хуже, чем утечка.

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

Да, вы можете сделать это. За исключением того, что вы должны освободить self.viewController, чтобы количество сохраняемых элементов равнялось 1 к концу фрагмента.

Давайте посчитаем. После выделения счетчик выпусков равен 1. При присвоении его self.viewController (при условии, что это свойство с поведением retain) увеличивает его до двух. Выпуская его в конце второго фрагмента, он снова становится равным 1. Идея состоит в том, что вы полностью освободите его в dealloc текущего класса, что бы это ни было.

Единственная проблема заключается в том, что освобождение объектной переменной предполагает, что вы закончили с ней, и здесь вам нужно перейти к выпуску self.viewController, но использовать его позже. Вроде вонючий.

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