Koleksi yang Tidak Dapat Diubah / Diubah di Swift

88

Saya mengacu pada panduan pemrograman Swift Apple untuk memahami pembuatan objek yang dapat diubah / tidak dapat diubah (Array, Dictionary, Sets, Data) dalam bahasa Swift. Tapi saya tidak mengerti cara membuat koleksi yang tidak bisa diubah di Swift.

Saya ingin melihat padanan di Swift untuk yang berikut di Objective-C

Array yang Tidak Dapat Diubah

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

Array yang Dapat Diubah

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

Kamus yang Tidak Dapat Diubah

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

Kamus yang Dapat Diubah

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

Jawaban:

115

Array

Buat array yang tidak bisa diubah

Cara pertama:

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

Cara kedua:

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

Buat array yang bisa berubah

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

Tambahkan objek ke larik

array.append("Forth")


Kamus

Buat kamus yang tidak dapat diubah

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

Buat kamus yang bisa berubah

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

Tambahkan pasangan baru ke kamus

dictionary["Item 3"] = "description"

Informasi lebih lanjut tentang Pengembang Apple

nicael
sumber
12
Larik "Panjang tetap" akan lebih tepat. Itu tidak bisa diubah.
Sulthan
1
tidak Dictionarydapat diubah benar-benar tidak dapat diubah (berlawanan dengan Array)
Bryan Chen
@BryanChen Oh .. Terima kasih!
nicael
@BryanChen Ya, saya lupa menghapus var.
nicael
2
Ya. Info lebih lanjut tentang kekekalan array dalam pertanyaan ini dan jawabannya .
Matt Gibson
31

Swift tidak memiliki penurunan apa pun sebagai pengganti NSArrayatau kelas koleksi lainnya di Objective-C.

Ada kelas array dan kamus, tetapi perlu dicatat ini adalah tipe "nilai", dibandingkan dengan NSArray dan NSDictionary yang merupakan tipe "objek".

Perbedaannya tidak kentara tetapi bisa sangat penting untuk menghindari bug kasus tepi.

Dengan cepat, Anda membuat larik "tidak berubah" dengan:

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

Dan array "bisa berubah" dengan:

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

Array yang dapat berubah dapat dimodifikasi seperti NSMutableArray:

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

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

Namun Anda tidak bisa meneruskan array yang bisa berubah ke suatu fungsi:

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

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

Tetapi kode di atas berfungsi dengan NSMutableArray:

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

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

addToArray(myArray)

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

Anda dapat mencapai NSMutableArrayperilaku dengan menggunakan inoutparameter metode:

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

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

addToArray(&myArray)

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

Tulis ulang jawaban ini 2015-08-10 untuk mencerminkan perilaku Swift saat ini.

Abhi Beckert
sumber
1
Ini jelas telah diubah sekarang. Larik konstan sekarang benar-benar tidak berubah, dan larik variabel sekarang benar-benar bisa berubah. Mereka dikirimkan sebagai nilai , oleh karena itu mereka akan disalin ketika ditugaskan ke variabel lain atau diteruskan antar fungsi. Ini, bagaimanapun, tidak ada hubungannya dengan mutabilitas atau kekekalan.
Balthazar
Juga seperti yang saya sebutkan dalam jawaban saya, dilewatkan sebagai nilai yang relevan dengan mutabilitas / kekekalan karena satu-satunya saat Anda peduli adalah ketika meneruskan array ke kode lain (yang dapat memodifikasinya).
Abhi Beckert
Tetapi jika Anda mengakses array sebagai properti, Anda masih dapat memodifikasinya dari objek lain. Salah satu keuntungan dari larik yang tidak dapat diubah, adalah Anda dapat meneruskannya dengan aman ke objek lain, tanpa mengkhawatirkan apakah objek lain dapat mengubah aslinya. Kekhawatiran ini tidak ada lagi saat objek diteruskan sebagai nilai. Jadi, semantik yang berbeda membutuhkan praktik pengkodean yang berbeda. EDIT: Saya sekarang melihat Anda telah menulis ulang postingan, jadi kami setuju. Saya setuju perbedaan itu penting untuk diperhatikan wrt. penggunaan koleksi yang bisa berubah.
Balthazar
6

Hanya ada satu Arraydan satu Dictionarytipe di Swift. Mutabilitas tergantung pada bagaimana Anda membangunnya:

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

yaitu jika Anda membuat sebuah assign ke variabel itu bisa berubah, sedangkan jika Anda membuat assign ke konstan itu tidak.

PERINGATAN: Array yang tidak dapat diubah tidak sepenuhnya tidak dapat diubah! Anda masih dapat mengubah isinya, hanya saja tidak panjangnya secara keseluruhan!

ColinE
sumber
1
FYI: perilaku array berubah dalam versi beta yang akan datang; Saya pikir semua orang
bertukar pikiran
@xenadu Sumber? ETA dalam versi beta itu?
File Analog
Maaf, tidak ada sumber. Itu berasal dari diskusi dengan salah satu anggota tim penyusun. Dia juga mengatakan Beta 2 pada dasarnya hanya beberapa dari perbaikan bug yang sudah diperiksa dan tidak ada hubungannya dengan umpan balik pasca-WWDC.
russbishop
5

Cukup nyatakan objek atau variabel Anda (apa saja) dengan

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

dan

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

Untuk informasi lebih dalam

“Gunakan let untuk membuat konstanta dan var untuk membuat variabel. Nilai konstanta tidak perlu diketahui pada waktu kompilasi, tetapi Anda harus menetapkan nilai tepat satu kali. Ini berarti Anda dapat menggunakan konstanta untuk memberi nama nilai yang Anda tentukan sekali tetapi digunakan di banyak tempat. "

var myVariable = 42
myVariable = 50
let myConstant = 42

Baca “Bahasa Pemrograman Swift.”

iPatel
sumber
Nah, dalam kasus Array ini tidak berfungsi seperti yang diharapkan. stackoverflow.com/a/24319712/623710
macshome
3

Jika Anda ingin menggunakan Array(Swift) sebagai dengan NSArray, Anda dapat menggunakan fungsi jembatan sederhana. Contoh:

var arr1 : Array = []

arr1.bridgeToObjectiveC().count

Ini bekerja sama untuk let.

Moti F.
sumber
0

Dari dokumen Apple sendiri:

Mutabilitas Koleksi

Jika Anda membuat larik, kumpulan, atau kamus dan menetapkannya ke variabel, koleksi yang dibuat akan bisa berubah. Ini berarti Anda dapat mengubah (atau memutasi) koleksi setelah dibuat dengan menambahkan, menghapus, atau mengubah item dalam koleksi. Sebaliknya, jika Anda menetapkan larik, himpunan, atau kamus ke konstanta, koleksi tersebut tidak dapat diubah, dan ukuran serta isinya tidak dapat diubah.

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

Penggunaan lain dari koleksi yang tidak dapat diubah / dapat diubah bergantung pada mengapa Anda ingin koleksi tersebut dapat diubah / tidak dapat diubah. Koleksi adalah tipe nilai di Swift, yang berarti isinya disalin ketika ditetapkan ke nilai lain, atau diteruskan ke fungsi / metode lain. Oleh karena itu, Anda tidak perlu khawatir tentang apakah fungsi metode penerima dapat mengubah larik asli. Oleh karena itu, Anda tidak perlu memastikan untuk mengembalikan koleksi yang tidak dapat diubah jika kelas Anda memiliki koleksi yang bisa berubah, misalnya.

Balthazar
sumber
0

[Tidak Dapat Dimodifikasi dan Tidak Dapat Diubah]

Array Swift bisa dibungkam

[let vs var, Nilai vs Jenis Referensi]

Koleksi yang tidak dapat diubah [Tentang] yang tidak dapat diubah - adalah struktur koleksi yang tidak dapat diubah. Artinya Anda tidak dapat menambah, menghapus, memodifikasi setelah pembuatan

let + struct(seperti Array, Set, Dictionary) lebih cocok untuk menjadi abadi

Ada beberapa kelas (mis NSArray ) yang tidak menyediakan antarmuka untuk mengubah keadaan bagian dalam

tapi

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

Ini lebih suka unmodifiablearray

yoAlex5
sumber