2009-05-25 4 views
8

Ho letto in diversi libri ... e online ... su stringhe immutabili e mutevoli. Sostengono che "le stringhe immutabili" non possono essere modificate. (ma non definiscono mai "modifica")L'ultima parola su NSStrings: Mutabile e Immutabile

Quale di queste NSStrings può essere modificata senza utilizzare NSMutableString?

La stringa contiene "pesce gatto" ... e in seguito cerco di cambiarlo in "gatto". (stesse lettere, solo più corte.)

Contiene "gatto" ... e provo a cambiarlo in "pesce gatto". (Inizio simile ... ma solo più lungo.)

Sostituisco "gatto" in "CAT". (stesse lettere, ma solo il caso è cambiato.)

Cambio "gatto" in "cane". (Stringa completamente diversa, ma della stessa lunghezza.)

Sostituisco "gatto" in "dogwood". (stringa completamente diversa, ma più lunga.)

+0

Quasi una domanda clintoniana! –

risposta

20

La risposta è - nessuno. Immutabile significa che non può essere modificato in in modo diverso da diverso dalla stringa originale. Ogni personaggio rimane lo stesso, la lunghezza non può cambiare, ecc. Una volta definita, non puoi cambiare nulla su quella stringa. Se vuoi renderlo più lungo o più corto o cambiare uno dei caratteri, devi creare una nuova stringa (o usare NSMutableString per iniziare).

+0

Grazie per la rapida risposta. Questo non rende NSString abbastanza inutile? Ho impostato un * VARIABLE * su un valore NSString ... e quindi non potrò mai cambiarlo. Non è comunemente chiamato "costante" in altre lingue? Vorrei (invece) probabilmente voler "fare qualcosa" con le mie punture il 99% delle volte. Quindi non dovrei usare MSMutableString quasi ovunque? (Ma raramente la vedo usata, confrontata con la NSString VERY comunemente usata.) – Donna

+0

Immaginate se int/float/long fossero anche immutabili. int x = 5; e quindi x can * MAI * essere modificato. Immutabile è (quasi) inutile. No? – Donna

+0

"fare qualcosa" potrebbe semplicemente implicare la loro lettura da qualche archivio dati e la loro visualizzazione. In questo caso non vorrai modificarli. – rein

2

è necessario definire "cambiamento", troppo :)

In sostanza, quando si crea un NSString, si sta creando un array di caratteri e si sta dicendo al compilatore che il contenuto di detto schieramento non cambierà mai. La parte "mai cambiare" è la parte "immutabile"; i dati contenuti nella stringa non possono essere modificati.

D'altra parte, NSMutableString consente di modificare effettivamente i dati a cui punta (quindi è 'mutabile'). Nota il metodo 'appendString' che esiste per NSMutableString; questo in realtà prende i dati e li schiaffa sulla fine della stringa.

Ad esempio, se si ha:

NSString * myString = @ "Cat"; myString = @ "Pesce rosso";

Ciò funzionerebbe correttamente. Non stai mai effettivamente cambiando i dati che myString contiene; stai semplicemente dicendo che vuoi che indichi un nuovo segmento di dati non modificabili.

L'unica volta in cui si incontrano effettivamente problemi con le differenze tra oggetti mutabili e immutabili è se si è tentato di modificare direttamente myString direttamente (ad esempio append "s cool" ad esso o qualcosa del genere).

In altre parole, entrambe le classi consentono di "modificare" qualsiasi stringa in qualsiasi altra stringa, ma i metodi utilizzati per farlo sarebbero molto diversi. Ad esempio, per trasformare "cat" in "CAT" con una stringa mutabile, puoi scorrere su ogni carattere e renderlo semplicemente in maiuscolo (dato che puoi modificare il contenuto di una stringa mutabile). Con una stringa immutabile, d'altra parte, dovresti prima copiare la stringa originale altrove, modificarla, quindi reindirizzare la tua variabile per puntare a questa nuova NSString.

I seguenti link potrebbero essere utili: http://www.kirupa.com/forum/showthread.php?t=307928 http://forums.macrumors.com/showthread.php?t=467099

Consiglio anche facendo un po 'googling; questa è una domanda che riguarda lo sviluppo in generale, ed è un concetto relativamente importante da comprendere. È stato anche discusso a morte altrove su Internet.

+0

Sarebbe più "sicuro" e "più flessibile" utilizzare NSMutableString ovunque? Dicono che c'è un "costo di memoria" e un "costo di velocità" ... ma ... quanto? 20 bytes extra dal mio pool di milioni? O rallentare la mia app di 0,01 secondi? (I vantaggi di "non doversi mai preoccupare dei mutabili" sembra valere la pena.) O lo è? – Donna

+1

Se stai usando una programmazione concorrente (thread multipli, ecc.) È molto bello sapere che il contenuto della tua stringa non cambierà nel mezzo del tuo utilizzo. Se dovessi preoccuparti di ciò, probabilmente farai una copia della stringa prima di fare qualsiasi altra cosa in modo che nessuno la cambierà. L'immutabilità fa in modo che tu non debba copiare la stringa. Ciò diventa ancora più importante per strutture più grandi come NSArray e NSDictionary. Se hai solo un thread (se non sai cosa significa, ne hai solo uno), allora usare i mutabili ovunque probabilmente sarebbe perfetto. –

+0

Anche se non si utilizza più di un thread, è bello sapere se un oggetto può cambiare da sotto di te. In generale trovo più semplice usare le strutture di dati immutabili per la maggior parte del tempo. Se creo un NSArray, lo do a qualcun altro e poi continuo a usarlo, è utile sapere se qualcuno potrebbe averlo cambiato alle mie spalle. In breve, usare il mutabile ovunque è più facile da scrivere, ma molto più difficile da eseguire il debug. – rpetrich

11

Se io dichiaro una variabile:

NSString * var; 
// Here some code giving a new value to var 

Ciò che è immutabile, è l'oggetto puntato da var, non var sé.

Ciò significa che non è possibile modificare nulla dell'oggetto puntato da var, ma è possibile modificare a quale oggetto è indirizzato.

Nessuna delle operazioni di cui parli è consentito il var, ma è possibile assegnare var con un'altra stringa diversa:

NSString * anotherVar; 
// Here some code giving a new value to anotherVar 

var = anotherVar; // This is allowed (with a memory leak if GC is disabled) 

// The following is also allowed: -stringWithFormat: creates a new object 
var = [var stringWithFormat:@"%@ with more chars", var]; 
+0

Giusto per notare, quel codice dovrebbe * non * provocare una perdita di memoria con GC disabilitato. Quello che stai facendo è un compito semplice, senza alcun -retain o -copy coinvolti. Quindi, nessuna perdita di memoria. Inoltre, il formato della stringa deve essere @ "% @ con più caratteri", poiché% s si applica solo alle stringhe C, credo. –

+0

Grazie, ho aggiornato il formato. Riguardo alla perdita di memoria, dipende da come è stato creato il primo valore di var. – mouviciel

2

Una stringa immutabile (o addirittura, qualsiasi oggetto immutabile) è uno che non può essere cambiato completamente dopo l'inizializzazione.

Ecco il vantaggio di utilizzare stringhe immutabili, in (pseudo) pseudo-codice:

// if using mutable strings 
let a = "Hello World"; 
let b = a; 
a.replace("Hello", "Goodbye"); 

Ora che cosa fa una stretta? "Ciao mondo"? "Addio mondo"? Ora che cosa tiene premuto b?

Se le stringhe sono modificabili, potrebbe contenere "Goodbye World". Questo potrebbe essere quello che vuoi. Potrebbe non essere.

Con immutabilità, diventa molto chiaro che b punta ancora sulla stringa originale, perché il metodo replace non può aver modificato la stringa effettiva, ma piuttosto ha restituito un riferimento a una nuova stringa.

In questo esempio potrebbe non essere di grande utilità. Ma se a e b sono referenziati e usati in diverse parti del codice, o in diversi thread, avere riferimenti immutabili rimuove molti potenziali errori.

3

NSString non può essere modificato, ogniqualvolta si assegna un valore di stringa all'oggetto NSString, esso diventa orfano dell'oggetto stringa vecchio e ricrea il nuovo oggetto stringa. Questa è un'operazione costosa se si ha a che fare con un buffer di stringa di grandi dimensioni. Se si ha a che fare con un buffer di stringa di grandi dimensioni, utilizzare NSMutableString per prestazioni ottimali. Questo è simile a string vs stringBuilder in .net.

1

Per impostazione predefinita, NSString utilizzato nel linguaggio obiettivo C è immutabile. NSMutableString viene utilizzato per dichiarare & definire una stringa mutabile. Nulla in una stringa immutabile può essere cambiato. Non la lunghezza, non i personaggi, niente.