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ì. Autorizzi sempre immediatamente a meno che tu non abbia una ragione specifica per non farlo.
Il primo motivo è che è molto facile dimenticare di scrivere il messaggio release
. Se autorizzi l'oggetto nella stessa dichiarazione in cui lo crei (come in [[[… alloc] init] autorelease]
), è molto più difficile dimenticarlo e molto più ovvio quando lo fai. I metodi Factory Convenience (come stringWithCapacity:
) autorizzano automaticamente l'oggetto per te, così come quando lo autorizzi tu stesso, non devi preoccuparti di rilasciarlo in seguito.
In secondo luogo, anche se ti ricordi di scrivere il messaggio separato release
, è facile non toccarlo. Due modi sono i primi ritorni:
NSString *str = [[NSString alloc] initWithString:@"foo"];
BOOL success = [str writeToFile:path atomically:NO];
if (!success)
return;
[str release];
e le eccezioni sollevate o 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 cui caso potresti voler gestire manualmente quanti più oggetti nel loop puoi, al fine di mantenere il tuo conto alla rovescia. Tuttavia, esegui questa operazione solo se hai la prova che questo è il tuo problema (che si tratti di numeri rigidi da squalo, numeri rigidi da strumenti o il tuo sistema che va all'inferno di paging ogni volta che il ciclo viene eseguito abbastanza a lungo).
Altre soluzioni, possibilmente migliori, includono la suddivisione del loop in due loop nidificati (quello esterno per creare e drenare un pool di autorelease per il loop interno) e passare a NSOperation. (Tuttavia, assicurarsi di impostare un limite al numero di operazioni la coda viene eseguito in un momento, altrimenti, you may make it even easier to go into paging hell.)
è anche la prima meglio in quanto dà al compilatore un senso di grandezza?
È meglio, ma non per questo motivo.
Al compilatore, è solo un altro messaggio di classe. Il compilatore non sa o si cura di quello che fa; per tutto ciò che sa e si preoccupa, stringWithCapacity:
è il messaggio per riprodurre un brano per l'utente.
Dà a NSMutableString un suggerimento per la dimensione: la classe saprà quanto spazio di memorizzazione dei caratteri potrebbe desiderare di allocare inizialmente. Qualunque sia il vantaggio che ottieni da questo è probabilmente piccolo (almeno sul Mac), ma se hai le informazioni a portata di mano, perché non usarlo? Al contrario, non andrei 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, vi è una certa quantità di rischio nel lasciare una variabile non inizializzata. Attivare definitivamente l'impostazione di generazione "Run Static Analyzer" se si decide di prendere l'abitudine.
+1, tranne per il fatto che non sono d'accordo con "Avvia sempre automaticamente l'autorizzazione a meno che tu non abbia una ragione specifica per non farlo". La tua giustificazione ("è molto facile dimenticare di scrivere il messaggio" release ") non è così rilevante ora che l'analizzatore statico catturerà facilmente questo errore. Personalmente evito gli oggetti autoreleased, solo per evitare il cumulo di autorelease pool e il colpo che può venire dal drenare un pool di autorelease molto grande (che sì, ho notato). Generalmente preferisco ammortizzare il costo della deallocazione eseguendolo non appena ragionevolmente possibile. –
L'analizzatore statico può impiegare un po 'di tempo per funzionare su qualche codice sorgente, quindi potresti non volerlo per tutto il tempo. E la maggior parte delle spese di drenaggio di un pool di autorelease è nel rilascio degli oggetti, che devi comunque fare. L'unica ragione che spicca è che li rilasci tutti (o alcuni di loro) in una sola volta invece di pochi millisecondi. –
NON rilasciare o autorelease fino alla fine del metodo. Qualsiasi messaggio successivo all'autorelease può potenzialmente svuotare il pool di autorelease. Se stai restituendo un oggetto autoreleased, non vuoi alcuna possibilità che venga distrutto prima che il chiamante lo ottenga. – NSResponder