Pergunta

Ainda um pouco confuso sobre o gerenciamento de memória Objective-C. Eu acho que a minha confusão decorre do que exatamente os meios disparo automático.

NSString *theBackendResponse = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSDictionary *accountDictionary = [theBackendResponse propertyList];
[viewController setAccountDictionary:accountDictionary];

Agora, o que devo fazer com o accountDictionary no método setAccountDictionary do meu controlador de vista? Agora eu apenas definir a variável de instância "accountDictionary" a tudo o que é retornado. Devo configurá-lo para um retido um, e em seguida, solte a única que voltou? O que devo dizer ao meu setter bloco de código semelhante, dado que o método PropertyList de NSString é autoreleased?

A propósito, se eu liberar theBackendResponse, eu vou perder o accountDictionary? Eu não supor ...

Foi útil?

Solução

Chamando [objectInstance autorelease] adiciona um objeto para o NSAutoreleasePool atual. Quando isso piscina recebe uma mensagem drain, ele envia uma release a todos os objetos na piscina. Se algum dos retainCount desses objetos chega a 0, eles são desalocados naquele ponto. A finalidade do disparo automático é para que você possa marcar um objeto para ser lançado "em algum momento no futuro." Isto é especialmente útil para coisas como métodos que retornam um objeto recém-alocado, mas querem liberá-lo para que o chamador não tem que assumir a propriedade do objeto retornado. Um método pode ter esta aparência:

- (id)myMethod {
    id myObj = [[SomeClass alloc] init];

    ...

    return [myObj autorelease];
}

O chamador de myMethod então retain o valor de retorno se eles queriam se apropriar do valor retornado ou ignorá-lo se não. Quando o NSAutoreleasePool atual é drenado, myObj receberá uma mensagem de liberação. Se não houver outros objetos ele próprio (ou seja, ter enviado uma mensagem retain), ele vai ficar desalocada.

Tudo isso é explicado no Gerenciamento de memória Cacau Guia de Programação . Mesmo se você já leu, vale sempre a pena uma outra leitura.

Assim, para responder às suas perguntas:

Primeiro, você deve liberar theBackendResponse. Você vai vazar memória se não o fizer. Você não precisa saber o que accountDictionary faz com a string: se ele precisa manter uma referência que vai ter retido theBackendResponse. Você tem uma propriedade de theBackendResponse porque você alloc'd-lo, então você deve abrir mão de que a propriedade (via release ou indiretamente via autorelease).

Em segundo lugar, você deve manter ou copiar o argumento para setAccountDictionary: se você quer manter uma referência a esse objeto ou valor, respectivamente. O método setter padrão é algo como isto (supondo que você não precisa semântica atômica):

-(void)setAccountDictionary:(NSDictionary*)newDict {
  if(newDict != accountDictionary) {
    id tmp = accountDictionary;
    accountDictionary = [newDict copy]; //Since newDict may be mutable, we make a copy so that accountDictionary isn't mutated behind our back.
    [tmp release];
  }
}

Você também deve se lembrar de release accountDictionary no método dealloc:

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

Uma vez que você parece estar usando NSViewController, eu suponho que você está no Leopard (OS X 10.5) e nesse caso, você provavelmente deve estar usando @property e se @synthesized getter / setter possível. Para fazer isso, adicione um

@property (copy,readwrite) NSDictionary * accountDictionary; 

declaração ao @interface classe. E adicionar uma directiva @synthesize accountDictionary; no bloco @implementation para sua classe controller.

Outras dicas

Em geral, um objeto ou método deve não precisa se preocupar sobre como outro é a gestão de memória. O fato de que alguém tenha autoreleased algo é irrelevante para você. É mais simples de pensar no conceito de propriedade . Então retain e alguns outros métodos reivindica a posse, e release e autorelease cedê-lo. Se um objeto precisa manter uma referência para outro, deve reivindicar a posse durante o tempo que ele precisa. Assim, métodos setter normalmente reter ou copiar o novo valor e liberar ou autorelease o valor antigo.

Eu recomendo fortemente a leitura as diretrizes de gerenciamento de memória Cacau . Eles não são tudo o que longo ou complicado, e é muito importante para compreendê-los.

O método set acessador deve sempre copy / retain o valor de entrada antes de liberar o velho, no caso em que o valor antigo é o único objeto que possui o novo valor:

-(void)setAccountDictionary:(NSDictionary*)newDict {
    id old = accountDictionary;
    accountDictionary = [newDict copy];
    [old release];
}

Se accountDictionary referido newDict ea contagem de reter por newDict foi de 1, a chamada para [accountDictionary release] antes da chamada para [newDict copy] faria com que a reter contar até cheguei a 0 e, portanto, liberar newDict.

Como exemplo de código incorreto, onde nós liberamos o dicionário de idade e, em seguida, copie o novo dicionário:

-(void)setAccountDictionary:(NSDictionary*)newDict {
    [accountDictionary release];
    accountDictionary = [newDict copy];
}

e têm o seguinte código:

NSDictionary *dict = [obj accountDictionary];
[obj setAccountDictionary:dict];

É inventado, mas demonstra que no setter, accountDictionary e newDict referem-se à mesma instância. Se a manter a contagem é 1, a linha [accountDictionary release] irá diminuir a contagem de reter a 0, e, assim, liberar a instância da memória. [newDict copy] agora irá referir-se a uma instância inválido.

Apple descreve vários conceitos ao implementar acessores: Memória Gestão Accessor métodos
Se você pode usar Objective-C 2.0, eu iria com propriedades e sintaxe de ponto. Propriedades são novos em Objective-C 2.0 e fornecer auto acessor geração.
No arquivo .h:

@property (retain) NSDictionary* accountDictionary;

Na implementação:

@synthesize accountDictionary;

Sintetizar gera métodos de acesso para a sua NSDictionary. (Se você quiser fornecer sua própria implementação, você também pode fazer isso)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top