2010-04-01 10 views
6

He visto esto por un tiempo y no entiendo por qué este simple código está arrojando un error. Acortado por brevedad:Anexar cadenas a NSMutableString

NSMutableString *output; 

... 

@property (nonatomic, retain) NSMutableString *output; 

... 

@synthesize output; 

... 

// logs "output start" as expected 
output = [NSMutableString stringWithCapacity:0]; 
[output appendString:@"output start"]; 
NSLog(@"%@", output); 

... 

// error happens here 
// this is later on in a different method 
[output appendString:@"doing roll for player"]; 

¿Alguien puede detectar mi error?

+0

¿Cuál es el error exacto? – outis

Respuesta

1

La solución de hecho tenía que ver con la retención, según lo indicado por el usuario invariant. El método de la clase:

output = [NSMutableString stringWithCapacity:0]; 

devuelve un autorelease NSMutableString. Cuando se asignó a mi propiedad de salida, aparentemente, incluso con la marca de retención, no la retuvo. La solución fue asignarlo yo mismo y no liberarlo de nuevo:

output = [[NSMutableString alloc] initWithCapacity:0]; 

Luego la retención funcionó. Cualquier explicación de por qué sería muy bienvenido.

Edición

descubierto por qué. Estaba accediendo a los vars de instancia directamente en lugar de a través del getter/setter que sinteticé. Más información en mi blog.

+0

Rufus de AppleDevForums me dio una muy buena respuesta a una cosa similar: – Emil

+1

Es extremadamente confuso, y las 7 u 8 cosas que necesitas saber para que esto finalmente tenga sentido no están en los mismos lugares. Primero, asuma que 'self.foo = bar;' es exactamente lo mismo que (un atajo de sintaxis para) '[self setFoo: bar];' Namely, "invoque el método" 'setFoo: bar'" en mí (este objeto) ". Ahora se estaría preguntando: "¿Eh? No escribí ningún método" setFoo ". Es cierto, no lo hiciste. La directiva @synthesize le dijo al compilador que escribiera el método "setFoo". – Emil

+0

Y el compilador no le proporciona el código fuente de este método que escribió para usted. Pero, ¿qué hace este método oculto "setFoo:"? 1. Comprueba si "bar" ya está configurado en "foo". 2. Si no es así, envía el mensaje de "liberación" a "foo" 3. Establece el puntero "foo" en la barra de puntero 4. Envía el mensaje "retener" a "foo" (SI La directiva @property para "foo" dice que lo haga). – Emil

2

Cambie la línea

output = [NSMutableString stringWithString:@"output start"]

a

[self setOutput:[NSMutableString stringWithString:@"output start"]]

(o self.output = ... si prefiere que la notación).

Aunque haya declarado una propiedad, no está utilizando el colocador, por lo que no está conservando la cadena.

+0

¿De verdad? Huh, es bueno saberlo. Pensé que cuando @synthesize una variable lo hace por mí. – typeoneerror