2010-04-01 21 views
6

Da un po 'di tempo lo stiamo osservando e non comprendendo perché questo semplice bit di codice genera un errore. Abbreviato per brevità:Aggiunta di stringhe 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"]; 

Qualcuno può individuare il mio errore?

+0

Qual è l'errore esatto? – outis

risposta

1

La soluzione ha effettivamente a che fare con la conservazione, come indicato dall'utente invariant. Il metodo della classe:

output = [NSMutableString stringWithCapacity:0]; 

restituisce una autorelease NSMutableString. Quando assegnato alla mia proprietà di output - apparentemente, anche con il flag di conservazione - non lo ha mantenuto. La soluzione era quella di alloc io stesso e non AutoRelease:

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

Poi il Retain lavorato. Qualsiasi spiegazione sul perché sarebbe molto gradita.

Modifica

capito perché. Stavo accedendo direttamente ai vars delle istanze invece che attraverso il getter/setter che ho sintetizzato. Maggiori informazioni sul mio blog.

+0

Rufus di AppleDevForums mi ha dato una buona risposta a una cosa simile: – Emil

+1

È estremamente confuso e le 7 o 8 cose che devi sapere per avere finalmente un senso non sono negli stessi posti. Per prima cosa, prendi fede che 'self.foo = bar;' è esattamente la stessa cosa di (una scorciatoia sintattica per) '[self setFoo: bar];' Vale a dire, "invoca il metodo" 'setFoo: bar'" su di me (questo oggetto). " Ora ti staresti chiedendo, "Huh? Non ho scritto alcun metodo" setFoo "." È vero, non l'hai fatto. La direttiva @synthesize diceva al compilatore di scrivere il metodo "setFoo". – Emil

+0

E il compilatore non ti fornisce il codice sorgente di questo metodo che ha scritto per te. Ma cosa fa questo metodo "setFoo:" nascosto? 1. Controlla se "bar" è già impostato su "foo". 2. In caso contrario, invia il messaggio "release" a "foo" 3. Imposta il puntatore "foo" sul puntatore "bar" 4. Invia il messaggio "retain" a "foo" (SE il @property direttiva per "foo" ha detto di farlo). – Emil

2

Modificare la linea

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

a

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

(o self.output = ... se si preferisce che la notazione).

Sebbene sia stata dichiarata una proprietà, non si sta utilizzando il setter, quindi non si manterrà la stringa.

+0

Davvero? Huh, buono a sapersi. Ho pensato che quando ho @sinteso una variabile lo faccio per me. – typeoneerror

Problemi correlati