Vamos começar com retain
e release
; autorelease
é realmente apenas um caso especial quando você entende os conceitos básicos.
No Cocoa, cada objeto controla quantas vezes está sendo referenciado (especificamente, a NSObject
classe base implementa isso). Ao chamar retain
um objeto, você está dizendo que deseja aumentar a contagem de referências em um. Ao ligar release
, você diz ao objeto que o está soltando e sua contagem de referência é diminuída. Se, após a chamada release
, a contagem de referência agora for zero, a memória desse objeto será liberada pelo sistema.
A maneira básica pela qual isso difere malloc
e free
é que um determinado objeto não precisa se preocupar com o travamento de outras partes do sistema, porque você liberou a memória que eles estavam usando. Supondo que todos estejam jogando junto e mantendo / liberando de acordo com as regras, quando um trecho de código retém e depois libera o objeto, qualquer outro trecho de código que também faça referência ao objeto não será afetado.
O que às vezes pode ser confuso é conhecer as circunstâncias em que você deve ligar retain
e release
. Minha regra geral é que, se eu quiser me apegar a um objeto por algum tempo (se for uma variável de membro de uma classe, por exemplo), preciso garantir que a contagem de referência do objeto saiba de mim. Como descrito acima, a contagem de referência de um objeto é incrementada chamando retain
. Por convenção, também é incrementado (realmente definido como 1) quando o objeto é criado com um método "init". Em qualquer um desses casos, é minha responsabilidade chamar release
o objeto quando terminar. Caso contrário, haverá um vazamento de memória.
Exemplo de criação de objeto:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Agora para autorelease
. A liberação automática é usada como uma maneira conveniente (e às vezes necessária) de instruir o sistema a liberar esse objeto depois de um tempo. Do ponto de vista do encanamento, quando autorelease
é chamado, o encadeamento atual NSAutoreleasePool
é alertado sobre a chamada. O NSAutoreleasePool
agora sabe que, quando obtiver uma oportunidade (após a iteração atual do loop de eventos), poderá chamar release
o objeto. Do nosso ponto de vista como programadores, ele cuida de release
nos chamar , para que não precisemos (e de fato não deveríamos).
O que é importante observar é que (novamente, por convenção) todos os métodos de classe de criação de objeto retornam um objeto liberado automaticamente. Por exemplo, no exemplo a seguir, a variável "s" tem uma contagem de referência 1, mas após a conclusão do loop de eventos, ela será destruída.
NSString* s = [NSString stringWithString:@"Hello World"];
Se você deseja pendurar nessa sequência, precisará chamar retain
explicitamente e, em seguida, explicitamente release
quando terminar.
Considere o seguinte código (muito elaborado) de código e você verá uma situação em que autorelease
é necessário:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
Sei que tudo isso é um pouco confuso - em algum momento, porém, ele clicará. Aqui estão algumas referências para você começar:
- Introdução da Apple ao gerenciamento de memória.
- Cocoa Programming for Mac OS X (4ª Edição) , de Aaron Hillegas - um livro muito bem escrito, com muitos ótimos exemplos. Lê como um tutorial.
- Se você está realmente mergulhando, pode ir para o Big Nerd Ranch . Esta é uma instalação de treinamento administrada por Aaron Hillegas - o autor do livro mencionado acima. Eu participei do curso Introdução ao cacau lá há vários anos e foi uma ótima maneira de aprender.