Niezmienne / zmienne kolekcje w języku Swift

88

Nawiązałem do przewodnika programowania Apple w języku Swift, aby zrozumieć tworzenie obiektów mutable / immutable (Array, Dictionary, Sets, Data) w języku Swift. Ale nie mogłem zrozumieć, jak stworzyć niezmienne kolekcje w Swift.

Chciałbym zobaczyć odpowiedniki w Swift dla poniższych w Objective-C

Niezmienna tablica

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

Mutable Array

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

Niezmienny słownik

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

Mutable Dictionary

NSMutableDictionary *mDictionary = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];
[mDictionary setObject:@"Value3" forKey:@"Key3"];
Pranav Jaiswal
źródło

Odpowiedzi:

115

Tablice

Utwórz niezmienną tablicę

Pierwszy sposób:

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

Drugi sposób:

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

Utwórz zmienną tablicę

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

Dołącz obiekt do tablicy

array.append("Forth")


Słowniki

Utwórz niezmienny słownik

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

Utwórz zmienny słownik

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

Dołącz nową parę do słownika

dictionary["Item 3"] = "description"

Więcej informacji na temat Apple Developer

nicael
źródło
12
Tablica o stałej długości byłaby bardziej precyzyjna. To nie jest niezmienne.
Sulthan,
1
immutable Dictionaryjest naprawdę niezmienny (w przeciwieństwie do Array)
Bryan Chen,
@BryanChen Oh .. Dzięki!
nicael
@BryanChen Tak, zapomniałem usunąć var.
nicael
2
Tak. Więcej informacji na temat niezmienności tablic w tym pytaniu i odpowiedzi na nie .
Matt Gibson,
31

Swift nie ma żadnego zamiennika NSArrayani innych klas kolekcji w Objective-C.

Istnieją klasy tablicowe i słownikowe, ale należy zauważyć, że są to typy „wartości” w porównaniu do NSArray i NSDictionary, które są typami „obiektowymi”.

Różnica jest subtelna, ale może być bardzo ważna, aby uniknąć błędów związanych z krawędziami.

W swift tworzysz „niezmienną” tablicę zawierającą:

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

Oraz tablicę „zmienną” zawierającą:

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

Mutowalne tablice można modyfikować tak jak NSMutableArray:

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

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

Jednak nie możesz przekazać zmiennej tablicy do funkcji:

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

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

Ale powyższy kod działa z NSMutableArray:

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

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

addToArray(myArray)

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

Możesz osiągnąć NSMutableArrayzachowanie za pomocą inoutparametru metody:

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

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

addToArray(&myArray)

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

Ponownie napisałem tę odpowiedź 10.08.2015, aby odzwierciedlić obecne zachowanie Swift.

Abhi Beckert
źródło
1
To oczywiście zostało teraz zmienione. Tablica stała jest teraz naprawdę niezmienna, a tablica zmiennych jest teraz naprawdę zmienna. Są przekazywane jako wartości , dlatego będą kopiowane po przypisaniu do innej zmiennej lub przekazywaniu między funkcjami. Nie ma to jednak nic wspólnego ze zmiennością lub niezmiennością.
Balthazar
Również, jak wspomniałem w mojej odpowiedzi, przekazywanie jako wartości jest istotne dla zmienności / niezmienności, ponieważ jedyny raz, na którym Ci zależy, to przekazywanie tablicy do innego kodu (który może ją modyfikować).
Abhi Beckert
Ale jeśli uzyskasz dostęp do tablicy jako właściwości, nadal możesz zmodyfikować ją z innego obiektu. Jedną z zalet niezmiennej tablicy jest to, że można bezpiecznie przekazać ją do innego obiektu, nie martwiąc się, czy inny obiekt może zmodyfikować oryginał. Ten problem już nie występuje, gdy obiekty są przekazywane jako wartości. Tak więc różne semantyki wymagają różnych praktyk kodowania. EDYCJA: Teraz widzę, że przeredagowałeś post, więc zgadzamy się. Zgadzam się, że różnice są ważne, aby być świadomym wrt. stosowanie zmiennych kolekcji.
Balthazar
6

W Swift jest tylko Arrayjeden Dictionarytyp. Zmienność zależy od tego, jak ją skonstruujesz:

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

tj. jeśli utworzysz przypisanie do zmiennej, jest ona zmienna, podczas gdy jeśli utworzysz przypisanie do stałej, nie jest.

OSTRZEŻENIE: Niezmienne tablice nie są całkowicie niezmienne! Nadal możesz zmienić ich zawartość, ale nie całkowitą długość!

ColinE
źródło
1
FYI: zachowanie tablicy zmienia się w nadchodzącej wersji beta; Myślę, że wszyscy o tym
gadali
@xenadu Source? ETA w tej wersji beta?
Plik analogowy
Przepraszam, brak źródła. Pochodzi z dyskusji z jednym z członków zespołu kompilatora. Powiedział również, że Beta 2 była w zasadzie tylko kilkoma już sprawdzonymi poprawkami błędów i nie ma nic związanego z opiniami po WWDC.
ruski biskup
5

Po prostu zadeklaruj swój (dowolny) obiekt lub zmienną za pomocą

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

i

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

Aby uzyskać głębsze informacje

„Użyj let, aby utworzyć stałą i var, aby utworzyć zmienną. Wartość stałej nie musi być znana w czasie kompilacji, ale należy przypisać jej wartość dokładnie raz. Oznacza to, że możesz użyć stałych do nazwania wartości, którą określasz raz, ale której używasz w wielu miejscach ”.

var myVariable = 42
myVariable = 50
let myConstant = 42

Przeczytaj „Swift Programming Language”.

iPatel
źródło
Cóż, w przypadku tablicy nie działa to zgodnie z oczekiwaniami. stackoverflow.com/a/24319712/623710
macshome
3

Jeśli chcesz pracować z Array(Swift) tak jak z NSArray, możesz użyć prostej funkcji pomostu. Przykład:

var arr1 : Array = []

arr1.bridgeToObjectiveC().count

Działa tak samo w przypadku let.

Moti F.
źródło
0

Z własnych dokumentów Apple:

Zmienność zbiorów

Jeśli utworzysz tablicę, zestaw lub słownik i przypiszesz je do zmiennej, utworzona kolekcja będzie modyfikowalna. Oznacza to, że możesz zmienić (lub zmutować) kolekcję po jej utworzeniu, dodając, usuwając lub zmieniając elementy w kolekcji. I odwrotnie, jeśli przypiszesz tablicę, zestaw lub słownik do stałej, ta kolekcja jest niezmienna, a jej rozmiaru i zawartości nie można zmienić.

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

Inne zastosowania niezmiennych / modyfikowalnych kolekcji zależą od tego, dlaczego chcesz, aby były mutowalne / niezmienne. Kolekcje są typami wartości w języku Swift, co oznacza, że ​​ich zawartość jest kopiowana, gdy zostanie przypisana do innej wartości lub przesłana do innej funkcji / metody. Dlatego nie musisz się martwić, czy funkcja metody odbierającej może zmienić oryginalną tablicę. Dlatego nie musisz zwracać niezmiennej kolekcji, jeśli na przykład Twoja klasa zawiera kolekcję mutowalną.

Balthazar
źródło
0

[Niemodyfikowalne i niezmienne]

Tablicę Swifta można wyciszyć

[let vs var, wartość vs typ odniesienia]

Niezmienna kolekcja [Informacje] - to struktura kolekcji, której nie można zmienić. Oznacza to, że nie możesz dodawać, usuwać, modyfikować po utworzeniu

let + struct(takie jak Array, Set, Dictionary) jest bardziej odpowiedni do niezmienne

Istnieje kilka klas (np. NSArray), Które nie zapewniają interfejsu do zmiany stanu wewnętrznego

ale

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)
}   

Wolałabym raczej unmodifiabletablica

yoAlex5
źródło