Когда авто-релиз на самом деле вызывает выпуск в Cocoa Touch? - PullRequest
11 голосов
/ 23 марта 2009

Я понимаю, что вы должны быть осторожны с autorelease на iOS. У меня есть метод, который возвращает объект alloc s, который нужен вызывающей стороне, поэтому в этой ситуации - насколько я понимаю - мне нужно отправить autorelease объекту в вызываемом объекте, прежде чем он вернется.

Это нормально, но как только управление возвращается на телефон (т. Е. После обработки моего нажатия кнопки), создается впечатление, что пул авто-релиза освобожден. Я подозреваю, что так и должно быть, но мне интересно, как лучше всего справиться с этой ситуацией.

Я прибег к отправке retain сообщения от вызывающей стороны, чтобы объект не был освобожден, а затем явно освободил его в dealloc.

Это лучший подход?

Ответы [ 5 ]

21 голосов
/ 23 марта 2009

Пул автоматического выпуска обычно освобождается после каждой итерации цикла выполнения. Грубо говоря, каждое приложение Cocoa и Cocoa Touch имеет следующую структуру:

Get the next message out of the queue
Create an autorelease pool
Dispatch the message (this is where your application does its work)
Drain the autorelease pool

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

13 голосов
/ 24 марта 2009

Использование autorelease - это способ сказать: «Объект, я больше не хочу тебя, но я передам тебя кому-то еще, кто может хотеть тебя, так что пока не исчезай». Таким образом, объект будет держаться достаточно долго, чтобы вы могли вернуть его из метода или передать другому объекту. Когда некоторый код хочет сохранить объект вокруг, он должен требовать владения, retain его.

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

3 голосов
/ 24 марта 2009

Вот пример, приведенный в документе Apple Memory Management :

– (id)findMatchingObject:(id)anObject 
{ 
    id match = nil; 
    while (match == nil) { 
        NSAutoreleasePool *subPool = [[NSAutoreleasePool alloc] init]; 
        /* Do a search that creates a lot of temporary objects. */ 
        match = [self expensiveSearchForObject:anObject]; 
        if (match != nil) { 
            [match retain]; /* Keep match around. */ 
        } 
        [subPool release]; 
    } 
    return [match autorelease];   /* Let match go and return it. */ 
}
2 голосов
/ 23 марта 2009

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

1 голос
/ 24 марта 2009

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

...