Domanda

La mia comprensione è che entrambi questi creare una NSMutableString, solo il primo è di proprietà di sistema e il secondo è di proprietà di me (cioè ho bisogno di rilasciarlo). C'è un motivo particolare per cui dovrei usare uno o l'altro, sulla faccia di esso sembra più facile da usare al primo? è anche il primo meglio in quanto dà al compilatore un senso di grandezza?

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

o

NSMutableString *newPath = [[NSMutableString alloc] init];

EDIT ... ANCHE

Vedo un sacco a dichiarazioni scritte su due linee (cioè.)

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];

Personalmente preferisco l'one-liner, è questo solo un altro esempio stile personale?

È stato utile?

Soluzione

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];
     

o

NSMutableString *newPath = [[NSMutableString alloc] init];
     

C'è un motivo particolare per cui dovrei usare uno o l'altro, sulla faccia di esso sembra più facile da usare al primo?

Sì. autorelease sempre immediatamente a meno che abbiate un motivo specifico per non farlo.

La prima ragione è che è molto facile dimenticare di scrivere il messaggio release. Se si autorelease l'oggetto nella stessa dichiarazione in cui si crea (come in [[[… alloc] init] autorelease]), è molto più difficile da dimenticare e più evidente quando si fa. I metodi di convenienza di fabbrica (come ad esempio stringWithCapacity:) autorelease l'oggetto per voi, così come quando si autorelease da soli, non c'è bisogno di preoccuparsi di rilasciare in un secondo momento.

In secondo luogo, anche se si ricorda di scrivere il messaggio release separata, è facile non colpirlo. Due modi sono i rendimenti prime:

NSString *str = [[NSString alloc] initWithString:@"foo"];

BOOL success = [str writeToFile:path atomically:NO];
if (!success)
    return;

[str release];

e gettato o eccezioni propagate:

NSString *str = [[NSString alloc] initWithString:@"foo"];

//Throws NSRangeException if str is not in the array or is only in the array as the last object
NSString *otherStr = [myArray objectAtIndex:[myArray indexOfObject:str] + 1];

[str release];

La “ragione specifica per non” è in generale che si ha un ciclo stretto che crea un sacco di oggetti, in questo caso si consiglia di gestire manualmente il maggior numero di oggetti nel ciclo, come si può, al fine di mantenere il valore del tuo oggetto verso il basso. Tuttavia, fare solo se si dispone di prove che questo è il tuo problema (che si tratti di numeri è difficile da Shark, i numeri duri Instruments, o il sistema di andare in paging inferno ogni volta che quel ciclo corre abbastanza a lungo).

altri, possibilmente migliori, soluzioni comprendono la divisione del ciclo in due cicli annidati (quella esterna per creare e scarico di una piscina autorelease per il ciclo interno) e passare a NSOperation. (Tuttavia, assicuratevi di impostare un limite su come molte operazioni la coda viene eseguito in un momento, altrimenti, si può rendere ancora più facile per andare in paging all'inferno .)

  

È anche la prima meglio in quanto dà al compilatore un senso di grandezza?

E 'meglio, ma non per questo.

Per il compilatore, è solo un altro messaggio di classe. Il compilatore non sa o cura ciò che fa; per tutto ciò che sa e si prende cura, stringWithCapacity: è il messaggio di suonare una canzone per l'utente.

Si dà NSMutableString una dimensione hint-classe sarà sapere quanto stoccaggio carattere che può decidere di allocare inizialmente. Qualunque beneficio che si ottiene da questo è probabilmente piccola (almeno su Mac), ma se avete le informazioni a portata di mano, perché non usarlo? Al contrario, non vorrei andare fuori dal mio modo di calcolarlo.

  

Vedo un sacco a dichiarazioni scritte su due linee (cioè.)

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];
     

Personalmente preferisco l'one-liner, è questo solo un altro esempio stile personale?

Sì. Tuttavia, v'è una certa quantità di rischio nel lasciare un non inizializzata variabile. Sicuramente accendere il “Run Static Analyzer” impostazione di compilazione se si decide di prendere l'abitudine di questo.

Altri suggerimenti

Il primo non è per il compilatore necessariamente, ma piuttosto un suggerimento per la stringa di come potrebbe essere in grado di ottimizzare la memorizzazione i dati. Ciò è particolarmente utile per NSDictionary / NSArray / NSSet, che hanno la capacità di internamente cambiare le loro implementazioni a seconda delle dimensioni dei loro dati set .

Oltre a questo, siete sulla strada giusta: l'unica differenza è una questione di proprietà. Ho quasi mai utilizzare i metodi WithCapacity, e piuttosto basta usare [NSMutableString string] o [NSMutableArray array], ma IMO, è davvero solo una questione di stile e tu non guadagnare o perdere nulla utilizzando uno sopra l'altro.

Il primo è una stringa autoreleased. Questo sarà rilasciato dal sistema al momento opportuno. Si aggiunge al pool autorelease e la memoria sarà gestito dal sistema. Una volta che è fuori portata, non si può garuntee che sarà valida. Questo tipo è utile se si ha solo ambito entro il metodo, e anche per la restituzione di valori dai metodi.

Il secondo è mantenuto, in modo avrà un conteggio di riferimento 1 e non viene aggiunto al pool autorelease. Lei è responsabile per rilasciarlo e liberando la memoria. Utilizzare questo metodo se si desidera controllare la portata dell'oggetto. Usato per le variabili membro, ecc.

Credo che la 2 linea di inizializzazione è solo lo stile, ma non vorrei utilizzare la variante 2 linea, come si sta definendo la variabile senza assinging un valore ad essa, anche se si è sulla riga successiva. Credo che questo tipo di specchi membro variabile dichiarazione / inizializzazione, ma io non personalmente piace molto.

far apparire le domande valide. Dipende da cosa si sta facendo, ma per applicazioni iPhone generale direi basta usare il primo. Questo sarà ripulito automaticamente per voi quando il conteggio di riferimento arriva a 0 e non dovete preoccuparvi di questo.

Con la seconda quando si hanno davvero un buon motivo per gestire la memoria della stringa da soli. Come ad esempio si vuole essere sicuri di quando la stringa dovrebbe essere ripulito, o che ci si aspetta di memoria per essere minimo in un determinato momento.

Direi che come regola generale utilizzare il secondo quando si ha una buona ragione per farlo.

Hai ragione su tutti i tuoi punti!

Non sono sicuro di quanto è grande la differenza delle dimensioni / capacità di suggerimento fa, ma ulteriori informazioni dovrebbe certamente consentire di run-time prendere decisioni migliori.

Perché utilizzare uno stile sopra l'altro? Beh, oggetti quando vengono rilasciati autoreleased? Ci sono due ragioni non banali, perché potrebbe importa. In primo luogo, quando un metodo utilizza un sacco di memoria che è possibile rilasciare immediatamente. (Si potrebbe anche usare un pool autorelease locale suppongo.) In secondo luogo, trovo che utilizzando autorelease può nascondere le perdite di memoria e fare il debug del codice più difficile. La vostra situazione potrebbe essere diversa a seconda dell'età e la qualità del codice.

Quando ho iniziato in via di sviluppo applicazioni per iPhone che ho usato oggetti autoreleased tutto il tempo. Era comodo perché non ho capito appieno come tutto ha funzionato e di solito ha fatto la cosa giusta. Questi giorni tendo sbagliare sul lato della memoria deallocazione manualmente. In realtà non è così difficile quando effettivamente capire come funziona il conteggio di riferimento e costringe il problema immediatamente quando non lo fai.

Se sei abbastanza sicuro per quanto tempo una stringa avrete bisogno, andare avanti e utilizzare il -initWithCapacity: metodo. Quando si supera memorizzazione di una stringa, viene riallocato e copiato, che non è un'operazione a buon mercato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top