Collezioni immutabili / mutevoli in Swift


88

Mi riferivo alla guida alla programmazione Swift di Apple per comprendere la creazione di oggetti mutabili / immutabili (array, dizionario, set, dati) in linguaggio Swift. Ma non riuscivo a capire come creare una raccolta immutabile in Swift.

Vorrei vedere gli equivalenti in Swift per quanto segue in Objective-C

Array immutabile

NSArray *imArray = [[NSArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];

Array mutevole

NSMutableArray *mArray = [[NSMutableArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];
[mArray addObject:@"Fourth"];

Dizionario immutabile

NSDictionary *imDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];

Dizionario mutevole

NSMutableDictionary *mDictionary = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];
[mDictionary setObject:@"Value3" forKey:@"Key3"];

Risposte:


115

Array

Crea array immutabile

Primo modo:

let array = NSArray(array: ["First","Second","Third"])

Secondo modo:

let array = ["First","Second","Third"]

Crea array mutevole

var array = ["First","Second","Third"]

Aggiungi oggetto all'array

array.append("Forth")


Dizionari

Crea un dizionario immutabile

let dictionary = ["Item 1": "description", "Item 2": "description"]

Crea un dizionario mutevole

var dictionary = ["Item 1": "description", "Item 2": "description"]

Aggiungi una nuova coppia al dizionario

dictionary["Item 3"] = "description"

Maggiori informazioni su Apple Developer


12
L'array "lunghezza fissa" sarebbe più preciso. Non è immutabile.
Sulthan

1
immutabile Dictionaryè veramente immutabile (al contrario di Array)
Bryan Chen

@BryanChen Oh .. Grazie!
nicael

@BryanChen Sì, ho dimenticato di rimuovere var.
nicael

2
Sì. Maggiori informazioni sulla non immutabilità degli array in questa domanda e nelle sue risposte .
Matt Gibson

31

Swift non ha alcun calo in sostituzione NSArrayo delle altre classi di raccolta in Objective-C.

Esistono classi di array e di dizionario, ma va notato che si tratta di tipi "valore", rispetto a NSArray e NSDictionary che sono tipi "oggetto".

La differenza è sottile ma può essere molto importante per evitare bug di casi limite.

In swift, crei un array "immutabile" con:

let hello = ["a", "b", "c"]

E un array "modificabile" con:

var hello = ["a", "b", "c"]

Gli array mutevoli possono essere modificati proprio come NSMutableArray:

var myArray = ["a", "b", "c"]

myArray.append("d") // ["a", "b", "c", "d"]

Tuttavia non puoi passare un array modificabile a una funzione:

var myArray = ["a", "b", "c"]

func addToArray(myArray: [String]) {
  myArray.append("d") // compile error
}

Ma il codice sopra funziona con un NSMutableArray:

var myArray = ["a", "b", "c"] as NSMutableArray

func addToArray(myArray: NSMutableArray) {
  myArray.addObject("d")
}

addToArray(myArray)

myArray // ["a", "b", "c", "d"]

È possibile ottenere NSMutableArrayil comportamento di utilizzando un inoutparametro del metodo:

var myArray = ["a", "b", "c"]

func addToArray(inout myArray: [String]) {
  myArray.append("d")
}

addToArray(&myArray)

myArray // ["a", "b", "c", "d"]

Ha riscritto questa risposta 2015-08-10 per riflettere l'attuale comportamento di Swift.


1
Questo ovviamente è stato cambiato ora. Un array costante è ora veramente immutabile e un array variabile è ora veramente mutabile. Vengono passati come valori , quindi verranno copiati quando assegnati a un'altra variabile o passati tra funzioni. Questo, tuttavia, non ha nulla a che fare con la mutabilità o l'immutabilità.
Balthazar

Inoltre, come ho menzionato nella mia risposta, essere passati come valori è rilevante per la mutabilità / immutabilità poiché l'unica volta che ti interessa è quando passi un array ad un altro codice (che potrebbe modificarlo).
Abhi Beckert

Ma se accedi all'array come proprietà, puoi comunque modificarlo da un altro oggetto. Uno dei vantaggi di un array immutabile è che puoi tranquillamente passarlo a un altro oggetto, senza preoccuparti se l'altro oggetto potrebbe modificare l'originale. Questa preoccupazione non esiste più quando gli oggetti vengono passati come valori. Quindi, semantiche diverse richiedono pratiche di codifica diverse. EDIT: ora vedo che hai riformulato il post, quindi siamo d'accordo. Sono d'accordo che le differenze sono importanti per essere consapevoli di wrt. l'uso di collezioni mutabili.
Balthazar

6

Ce n'è solo uno Arraye un Dictionarytipo in Swift. La mutabilità dipende da come la costruisci:

var mutableArray = [1,2,3]
let immutableArray = [1,2,3]

cioè se crei un'assegnazione a una variabile questa è mutabile, mentre se crei un'assegnazione a una costante non lo è.

ATTENZIONE: gli array immutabili non sono completamente immutabili! Puoi ancora modificare il loro contenuto, ma non la lunghezza totale!


1
FYI: il comportamento dell'array sta cambiando in una prossima beta; Penso che tutti si siano
accalcati

@xenadu Source? ETA su quella beta?
File analogico

Spiacenti, nessuna fonte. È venuto da una discussione con uno dei membri del team del compilatore. Ha anche detto che la Beta 2 era fondamentalmente solo un paio di correzioni di bug già verificate e non ha nulla a che fare con il feedback post-WWDC.
russbishop

5

Dichiara semplicemente il tuo (qualsiasi) oggetto o variabile con

'let' key word -> for "constan/Immutable" array, dictionary, variable, object..etc.

e

'var' key word -> for "Mutable" array, dictionary, variable, object..etc. 

Per informazioni più approfondite

“Usa let per creare una costante e var per creare una variabile. Non è necessario conoscere il valore di una costante in fase di compilazione, ma è necessario assegnargli un valore esattamente una volta. Ciò significa che puoi utilizzare le costanti per denominare un valore che determini una volta ma che utilizzi in molti punti.

var myVariable = 42
myVariable = 50
let myConstant = 42

Leggi "Il linguaggio di programmazione Swift".


Bene, nel caso di un array questo non funziona come previsto. stackoverflow.com/a/24319712/623710
macshome

3

Se vuoi lavorare con Array(Swift) come con NSArray, puoi usare una semplice funzione bridge. Esempio:

var arr1 : Array = []

arr1.bridgeToObjectiveC().count

Funziona allo stesso modo per let.


0

Dai documenti di Apple:

Mutevolezza delle collezioni

Se crei un array, un set o un dizionario e lo assegni a una variabile, la raccolta creata sarà modificabile. Ciò significa che puoi modificare (o mutare) la raccolta dopo che è stata creata aggiungendo, rimuovendo o modificando gli elementi nella raccolta. Al contrario, se si assegna un array, un set o un dizionario a una costante, quella raccolta è immutabile e la sua dimensione e il suo contenuto non possono essere modificati.

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-ID105

Altri usi delle raccolte immutabili / modificabili dipendono dal motivo per cui vuoi che siano mutabili / immutabili. Le raccolte sono tipi di valore in Swift, il che significa che il loro contenuto viene copiato quando viene assegnato a un altro valore o passato a un'altra funzione / metodo. Pertanto, non è necessario preoccuparsi se una funzione del metodo di ricezione potrebbe modificare l'array originale. Pertanto non è necessario assicurarsi di restituire una raccolta immutabile se la classe contiene una raccolta modificabile, ad esempio.


0

[Non modificabile e immutabile]

L'array di Swift può essere disattivato

[let vs var, Value vs Reference Type]

Raccolta immutabile [Informazioni su] - è una struttura di raccolta la cui struttura non può essere modificata. Significa che non puoi aggiungere, rimuovere, modificare dopo la creazione

let + struct(come Array, Set, Dictionary) è più adatto da essere immutabile

Ci sono alcune classi (ad esempio NSArray) che non forniscono un'interfaccia per cambiare lo stato interno

ma

class A {
    var value = "a"
}

func testMutability() {
    //given
    let a = A()
    
    let immutableArr1 = NSArray(array: [a])
    let immutableArr2 = [a]
    
    //when
    a.value = "aa"
    
    //then
    XCTAssertEqual("aa", (immutableArr1[0] as! A).value)
    XCTAssertEqual("aa", immutableArr2[0].value)
}   

Preferirebbe essere unmodifiablearray

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.