Objective-C: путаница с авто-выпуском - PullRequest
1 голос
/ 06 января 2012

Скажем, у меня есть класс DoStuff, и у этого класса есть два метода, например,

- (NSMutableDictionary* returnToCaller) methodOne : (NSString* ) myString {

    NSMutableDictionary* bundleOfJoy = [[NSMutableDictionary alloc] init]; 

    if (myString) { 
       bundleOfJoy = [self methodTwo];
    }

    return bundleOfJoy; 

} 

- (NSMutableDictionary* returnToMethodOne) methodTwo {

    NSMutableDictionary* anotherDictionary = [[NSMutableDictionary alloc] init]; 
    [anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];

    return anotherDictionary;  
}

хорошо, так что терпите меня, так как мое фу-менеджмент памяти слабоват.Я не могу освободить два словаря, созданные вручную после возврата, поскольку команда release не будет вызываться.Я не могу сделать это до возврата или я не передаю значения.Насколько я понимаю, способ справиться с этим - с помощью пула автоматического выпуска ...

pool = [[NSAutoreleasePool alloc] init];

и инициализации моих объектов как таковых

NSMutableDictionary* anotherDictionary = [[[NSMutableDictionary alloc] init] autorelease];

, а затем вызова

[pool drain];

Итак, если это правильно, где я могу инициировать пул?В пробуждении от ниб?И куда я могу позвонить [сток из бассейна]?

, если это неверно, может ли кто-нибудь выправить меня (но, пожалуйста, введите медленно): D

спасибо

Ответы [ 6 ]

2 голосов
/ 06 января 2012

Лучшее решение - использовать ARC. Тогда вам больше никогда не придется беспокоиться об этом. :)

Даже тогда вы должны понимать, что ARC делает для вас. Обсуждение в моей книге по программированию для iOS в равной степени относится к Mac OS X:

http://www.apeth.com/iOSBook/ch12.html#_memory_management

2 голосов
/ 06 января 2012

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

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

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
... create objects...
[pool drain];

Но, как я уже сказал, это просто вариант для особых случаев.

2 голосов
/ 06 января 2012

В большинстве случаев пул авторелизов уже настроен для вас.Если вы не запускаете код в отдельном потоке без использования GCD, вам не нужно выделять и истощать пул.Даже если вы добавили пул авто-релиза в этот метод, объект будет автоматически освобожден слишком рано, поскольку вам придется использовать его в том же методе.С учетом вышесказанного, чтобы получить автоматически выпущенный объект, вы можете использовать вспомогательный конструктор или добавить autorelease к вашему alloc/init.

- (NSMutableDictionary* /*returnToMethodOne*/) methodTwo {
    //Convenience constructor
    NSMutableDictionary* anotherDictionary = [NSMutableDictionary dictionary];
    //or    
    //NSMutableDictionary* anotherDictionary = [[[NSMutableDictionary alloc] init] autorelease]; 
    [anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];

    return anotherDictionary; 
}
2 голосов
/ 06 января 2012

Система поддерживает пул автоматического выпуска для вас. Он создается до запуска вашей программы и регулярно очищается, когда цикл обработки событий получает контроль. В большинстве случаев вам не нужен собственный пул автоматического выпуска: просто позвоните autorelease перед возвратом объекта, и все будет в порядке.

P.S. Если вы хотите узнать о ситуациях, когда вам нужен собственный пул автоматического выпуска, Apple подготовит для вас замечательное руководство .

2 голосов
/ 06 января 2012

В каждом потоке есть автоматический NSAutoreleasePool, и вам не нужно его создавать, вместо этого вы создаете новый поток.

Use [pool release];вместо [утечки пула], если только у вас нет утечки памяти.

За ваш код ответственность за метод освобождает выделенный объект, поэтому добавьте

 return [bundleOfJoy autorelease]; 
 return [anotherDictionary autorelease];
1 голос
/ 06 января 2012

Вам нужно autorelease объектов, которые вы возвращаете. Они будут существовать для вашего вызывающего кода, но будут выпущены в произвольный момент позже.

- (NSMutableDictionary* returnToMethodOne) methodTwo {
    NSMutableDictionary* anotherDictionary = [[NSMutableDictionary alloc] init]; 
    [anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];

    return [anotherDictionary autorelease]; 
}

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

Другим способом реализации этой функциональности может быть создание объекта с автоматическим выпуском, для которого вам не нужно управлять памятью (используя удобный конструктор). Например:

- (NSMutableDictionary* returnToMethodOne) methodTwo {
    NSMutableDictionary* anotherDictionary = [NSMutableDictionary dictionary]; // Creates an autoreleased NSMutableDictionary object.
    [anotherDictionary setObject: @"hardcodedstring" forKey: @"theKey"];

    return anotherDictionary; // No `autorelease` call because it's not our memory to manage.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...