Pergunta

Eu tenho a seguinte classe de exemplo:

Test.h:

@interface Test : UIButton {
    NSString *value;
}
- (id)initWithValue:(NSString *)newValue;
@property(copy) NSString *value;

Test.m:

@implementation Test
@synthesize value;
- (id)initWithValue:(NSString *)newValue {
    [super init];   
    NSLog(@"before nil value has retain count of %d", [value retainCount]);
    value = nil;
    NSLog(@"on nil value has retain count of %d", [value retainCount]);
    value = newValue;
    NSLog(@"after init value has retain count of %d", [value retainCount]);
    return self;
}

Que produz o seguinte resultado:

2008-12-31 09:31:41.755 Concentration[18604:20b] before nil value has retain count of 0
2008-12-31 09:31:41.756 Concentration[18604:20b] on nil value has retain count of 0
2008-12-31 09:31:41.757 Concentration[18604:20b] after init value has retain count of 2147483647

Eu estou chamando-o como:

Test *test = [[Test alloc] initWithValue:@"some text"];

não deve ter um valor de manter a contagem de 1? o que estou perdendo?

Obrigado por sua ajuda.

Foi útil?

Solução 5

Você tem uma referência a uma cadeia imutável. Atribuição não precisa copiar o valor (os dados string), já que é imutável. Se você fizer uma operação mutável, como valor = [newValue uppercaseString], então ele deve copiar os bits em valor e de valor manter a contagem incrementado.

Outras dicas

Não olhe para manter a contagem. Eles não são úteis e só vai enganá-lo - você não pode ter a certeza de que nada mais é reter um objeto, que um objeto que você começa de algum lugar não é compartilhada

.

Em vez disso, concentrar-se em propriedade do objeto e seguir o regras de gerenciamento de memória cacau para a carta. Dessa forma, o gerenciamento de memória será correta não importa o que otimizações Cacau pode estar fazendo nos bastidores para você. (Por exemplo, implementar -copy como apenas -retain para objetos imutáveis.)

Além disso, é crítico para entender a diferença entre Propriedades de seus objetos e variáveis ?? exemplo dentro de seus objetos. No código da sua pergunta, você está atribuindo um valor a uma variável de instância. Essa variável de instância é apenas isso: uma variável. Atribuindo a ele irá se comportar como qualquer outra atribuição de variável. Para usar a propriedade, você deve usar sintaxe de ponto ou sintaxe suporte para realmente invocar método setter da propriedade:

self.value = newValue;     // this is exactly equivalent to the next line
[self setValue:newValue];  // this is exactly equivalent to the previous line

O código gerado para a sintaxe de ponto e a sintaxe suporte é idêntica, e nem irá acessar a variável de instância diretamente.

Você está passando uma string literal. O compilador provavelmente aloca-lo na memória estática e define a manter a contagem para o valor máximo possível.

Tente uma string alocada dinamicamente em vez disso e ver o que acontece.

NSString* string = [[NSString alloc] initWithString: @"some text"];
Test* test = [[Test alloc] initWithValue: string];

Você está passando em uma constante string, que realmente não pode ser desalocada. Eu acho que é provavelmente 2147483647 UINT_MAX, que basicamente significa que o objeto não pode ser liberado.

Eu acho que você quer fazer isso:

self.value = newValue;

que irá invocar o setter da propriedade e fazer com que a cópia de ocorrer. "Value = newValue" simplesmente atribui um valor de ponteiro para a variável de instância.

Você não deve estar prestando atenção ao reter contagem, basta seguir as regras de gerenciamento de memória Cacau. http://iamleeg.blogspot.com/2008/12/cocoa- memória de management.html

hmm .. estamos chegando mais perto.

parece que manter a contagem de newValue também é 2147483647.

Eu tentei alocar dinamicamente a string em vez com os mesmos reter resultados da contagem.

Eu encontrei um artigo útil aqui: http://www.cocoadev.com/index. pl? NSString

FTA:

O NSString retornado por @ "" necessidade de ser liberado, ou é autoreleased? Nem. @ "" - cordas são de classe NSConstantString ?, e assim actuar como átomos no cicio; eles ficam em torno. Ou seja, se você usar @ "vaca" em dois locais distintos no seu código, eles serão referenciando o mesmo objeto. Eu não acho que -release ou -autorelease faz nada para nenhum deles.

Se eu tiver "cópia" na propriedade, porém, não deveria copiar o conteúdo da memória de destino em nova memória com uma reter contar de 1? Parece o atributo cópia não faz nada neste caso?

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    char *cstr = "this is a c string";

    NSString *str = [[NSString alloc] initWithUTF8String:cstr];
    NSLog(@"rc1: %d", [str retainCount]);

    [pool drain];
    return 0;
}

Se você executar o código acima, ele irá exibir uma contagem de 1

reter

Em Cacau, muitos objetos imutáveis ??simplesmente manter-se quando você pedir uma cópia da mesma zona. Se o objeto não está garantido para a mudança (ou seja, a sua imutabilidade), em seguida, uma cópia exata é redundante.

Em Objective-C, a classe string constante é separado para a aula NSString de cacau, embora possa ser uma subclasse de NSString (Eu não estou muito certo). Esta classe string constante pode substituir métodos de NSObject como retain, release e dealloc para que eles não fazem nada, e também substituir retainCount para que ele sempre retorna o mesmo número, UINT_MAX ou assim. Isso ocorre porque um string constante Objective-C é criada na memória estática. Ele deve ter o comportamento geral global de um objeto Cocoa (ao usar cacau), de modo que ele pode ser adicionado a matrizes, usadas como chaves para um dicionário etc, exceto no que diz respeito à sua gestão de memória, uma vez que foi alocada de forma diferente.

Disclaimer:. Eu realmente não sei o que estou falando

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