berilium: Benar sekali. vladof81: Tentu saja tidak.
gnasher729
Jawaban:
511
NSArray*array=[mutableArray copy];
Copymembuat salinan yang tidak dapat diubah. Ini cukup berguna karena Apple dapat melakukan berbagai optimasi. Misalnya mengirim copyke array yang tidak dapat diubah hanya mempertahankan objek dan kembali self.
Jika Anda tidak menggunakan pengumpulan sampah atau ARC ingat bahwa -copymempertahankan objek.
jawaban ini bagus, tetapi bagaimana saya bisa tahu dari dokumen yang copymenciptakan NSArray normal dan bukan NSMutableArray?
Dan Rosenstark
22
@ Yar: Anda melihat dokumentasi NSCopying yang menyatakan di sana: copyWithZone Salinan yang dikembalikan tidak dapat diubah jika pertimbangan "tidak berubah vs berubah" berlaku untuk objek penerima; jika tidak, sifat tepat dari salinan ditentukan oleh kelas.
Georg Schölly
1
Sangat rapi - Saya lebih suka solusi ini dari m5h. Keduanya singkat dan lebih efisien.
David Snabel-Caunt
1
Saya setuju David, memperbarui tanggapan saya untuk menunjukkan tanggapan ini.
hallski
2
@Rad: Itu hanya berarti kelas yang memiliki implementasi yang bisa berubah dan tidak dapat diubah. Mis. NSArray& NSMutableArray, NSString& NSMutableString. Tapi tidak misalnya NSViewControlleryang selalu berisi keadaan bisa berubah.
Georg Schölly
361
An NSMutableArrayadalah subkelas NSArraysehingga Anda tidak perlu selalu mengonversi tetapi jika Anda ingin memastikan bahwa array tidak dapat dimodifikasi, Anda dapat membuat NSArraysalah satu dari cara ini tergantung pada apakah Anda ingin autoreleased atau tidak:
/* Not autoreleased */NSArray*array=[[NSArray alloc] initWithArray:mutableArray];/* Autoreleased array */NSArray*array=[NSArray arrayWithArray:mutableArray];
EDIT: Solusi yang disediakan oleh Georg Schölly adalah cara yang lebih baik untuk melakukannya dan jauh lebih bersih, terutama sekarang kita memiliki ARC dan bahkan tidak perlu memanggil autorelease.
Bisakah saya melakukan (NSArray *) myMutableArray?
Vojto
2
Ya, karena NSMutableArray adalah subkelas dari NSArray yang valid.
hallski
4
Namun, casting ke (NSArray *) masih memungkinkan cast kembali ke (NSMutable *). Bukankah begitu?
Sharar
1
@ Sharvey: Ya, itu benar. Anda akan mendapatkan peringatan jika Anda tidak melakukan cast tetapi langsung menugaskan superclass ke subclass. Biasanya, Anda ingin mengembalikan salinan yang tidak dapat diubah, karena itulah satu-satunya cara untuk memastikan, bahwa array Anda benar-benar tidak akan dimodifikasi.
Georg Schölly
1
Sebelumnya Itu dikenal sebagai "Upcasting" (NSArray *) myMutableArray dan kebalikannya disebut "Downcasting"
Ini sangat salah. Baru diperiksa. [mutableArray copy] juga mengembalikan array kosong.
durazno
@durazno Tidak salah. Periksa tes Anda. Jika [mutableArray copy] mengembalikan array kosong, maka mutableArray pastilah array kosong. Jawaban saya hanya berlaku ketika mutableArray nihil.
Richard Venable
Meskipun ini benar, saya merasa Anda kehilangan kebenaran yang lebih mendasar dalam contoh Anda. Karena Anda telah menetapkan mutableArray sebagai nil, [mutableArray copy]dapat disederhanakan menjadi [nil copy]. Dalam tujuan-c setiap pesan yang dikirim ke nil akan selalu nihil. Sangat penting untuk mengingat perbedaan antara "tidak ada" dan "array tanpa apa pun di dalamnya".
mkirk
@ mkirk Jangan mengalihkan perhatian dari pertanyaan: "Bagaimana cara saya mengkonversi NSMutableArray ke NSArray?" Ada 2 solusi utama, dan perbedaan utama di antara mereka adalah bagaimana mereka berperilaku ketika array bisa berubah nihil.
Apa yang dilakukan yang tidak dilakukan orang lain?
Ben Leggiero
5
Objektif-C
Di bawah ini adalah cara untuk mengkonversi NSMutableArray ke NSArray:
//oldArray is having NSMutableArray data-type.//Using Init with Array method.NSArray*newArray1 =[[NSArray alloc]initWithArray:oldArray];//Make copy of arrayNSArray*newArray2 =[oldArray copy];//Make mutablecopy of arrayNSArray*newArray3 =[oldArray mutableCopy];//Directly stored NSMutableArray to NSArray.NSArray*newArray4 = oldArray;
Cepat
Di Swift 3.0 ada tipe data baru Array . Deklarasikan Array menggunakan letkata kunci maka akan menjadi NSArray Dan jika menyatakan menggunakan varkata kunci maka itu menjadi NSMutableArray .
Bagian Swift tidak sepenuhnya benar. Lihat di sini dan di sini untuk perbedaan antara bisa berubah / tidak berubah Arraydan NSArray/ NSMutableArrays. Mereka tidak sama.
[mutableArray copy]Antipattern ini adalah seluruh kode sampel. Berhentilah melakukannya untuk array yang dapat dipindahkan yang sementara yang transien dan dapatkan deallocated pada akhir lingkup saat ini.
Tidak ada cara runtime dapat mengoptimalkan pemborosan dari array yang bisa berubah yang baru saja akan keluar dari ruang lingkup, didekomposisi menjadi 0 dan dialokasikan untuk selamanya.
Menetapkan suatu NSMutableArrayke suatu NSArrayvariabel tidak akan menyamarkannya (yang merupakan pertanyaan OP tentang). Mengekspos nilai seperti itu (misalnya sebagai nilai balik atau sebagai properti) dapat mengakibatkan masalah yang sangat sulit untuk di-debug jika nilai itu secara tak terduga bermutasi. Ini berlaku untuk mutasi internal dan eksternal karena nilai yang dapat diubah dibagikan.
David Rönnqvist
Untuk menonaktifkan array itu, Anda harus [NSMutableArray arrayWithArray: ... atau sesuatu seperti itu.
Anton Tropashko
Belum tentu. Cukup dengan menugaskannya ke NSMutableArrayvariabel sudah cukup. Karena objek tidak pernah berhenti menjadi array yang dapat diubah, memanggil metode yang bermutasi padanya akan berhasil dan mengubah data yang dibagikan. Jika di sisi lain array yang dapat diubah asli disalin — mengubahnya ke array yang tidak dapat diubah - dan kemudian ditugaskan ke NSMutableArrayvariabel dan memiliki metode mutasi yang memanggilnya, panggilan tersebut akan gagal dengan doesNotRespondToSelectorkesalahan karena objek yang menerima panggilan metode mutasi ada di Bahkan tidak berubah dan tidak menanggapi metode-metode itu.
David Rönnqvist
ok, ini mungkin memiliki beberapa manfaat bagi pengembang yang tidak mengindahkan kompiler yang memperingatkan tentang tugas konversi tyope
Anton Tropashko
1
Jika Anda membuat array melalui mutabilitas dan kemudian ingin mengembalikan versi yang tidak dapat diubah, Anda bisa mengembalikan array yang bisa diubah sebagai "NSArray" melalui pewarisan.
Jika Anda "mempercayai" penelepon untuk memperlakukan objek kembali (secara teknis masih bisa berubah) sebagai NSArray yang tidak berubah, ini adalah opsi yang lebih murah daripada [mutableArray copy].
Untuk menentukan apakah itu dapat mengubah objek yang diterima, penerima pesan harus bergantung pada tipe formal nilai pengembalian. Jika ia menerima, misalnya, objek array yang diketik sebagai tidak dapat diubah, ia tidak boleh mencoba untuk mengubahnya . Ini bukan praktik pemrograman yang dapat diterima untuk menentukan apakah suatu objek dapat diubah berdasarkan keanggotaan kelasnya.
Praktik di atas dibahas secara lebih rinci di sini:
saya sedang mencari jawaban di swift 3 dan pertanyaan ini ditunjukkan sebagai hasil pertama dalam pencarian dan saya mendapatkan inspirasi jawabannya dari itu jadi di sini adalah kode 3 cepat
let array:[String]= nsMutableArrayObject.copy() as![String]
NSArray *array = [mutableArray copy];
NSArray *array = mutableArray;
Jawaban:
Copy
membuat salinan yang tidak dapat diubah. Ini cukup berguna karena Apple dapat melakukan berbagai optimasi. Misalnya mengirimcopy
ke array yang tidak dapat diubah hanya mempertahankan objek dan kembaliself
.Jika Anda tidak menggunakan pengumpulan sampah atau ARC ingat bahwa
-copy
mempertahankan objek.sumber
copy
menciptakan NSArray normal dan bukan NSMutableArray?NSArray
&NSMutableArray
,NSString
&NSMutableString
. Tapi tidak misalnyaNSViewController
yang selalu berisi keadaan bisa berubah.An
NSMutableArray
adalah subkelasNSArray
sehingga Anda tidak perlu selalu mengonversi tetapi jika Anda ingin memastikan bahwa array tidak dapat dimodifikasi, Anda dapat membuatNSArray
salah satu dari cara ini tergantung pada apakah Anda ingin autoreleased atau tidak:EDIT: Solusi yang disediakan oleh Georg Schölly adalah cara yang lebih baik untuk melakukannya dan jauh lebih bersih, terutama sekarang kita memiliki ARC dan bahkan tidak perlu memanggil autorelease.
sumber
Saya menyukai kedua solusi utama:
Atau
Perbedaan utama yang saya lihat di dalamnya adalah bagaimana mereka berperilaku ketika mutableArray nihil :
sumber
[mutableArray copy]
dapat disederhanakan menjadi[nil copy]
. Dalam tujuan-c setiap pesan yang dikirim ke nil akan selalu nihil. Sangat penting untuk mengingat perbedaan antara "tidak ada" dan "array tanpa apa pun di dalamnya".Anda mencoba kode ini ---
dan
sumber
Objektif-C
Di bawah ini adalah cara untuk mengkonversi NSMutableArray ke NSArray:
Cepat
Di Swift 3.0 ada tipe data baru Array . Deklarasikan Array menggunakan
let
kata kunci maka akan menjadi NSArray Dan jika menyatakan menggunakanvar
kata kunci maka itu menjadi NSMutableArray .Kode sampel:
sumber
Array
danNSArray
/NSMutableArray
s. Mereka tidak sama.Dalam tujuan-c:
Dengan cepat:
sumber
[mutableArray copy]
Antipattern ini adalah seluruh kode sampel. Berhentilah melakukannya untuk array yang dapat dipindahkan yang sementara yang transien dan dapatkan deallocated pada akhir lingkup saat ini.Tidak ada cara runtime dapat mengoptimalkan pemborosan dari array yang bisa berubah yang baru saja akan keluar dari ruang lingkup, didekomposisi menjadi 0 dan dialokasikan untuk selamanya.
sumber
NSMutableArray
ke suatuNSArray
variabel tidak akan menyamarkannya (yang merupakan pertanyaan OP tentang). Mengekspos nilai seperti itu (misalnya sebagai nilai balik atau sebagai properti) dapat mengakibatkan masalah yang sangat sulit untuk di-debug jika nilai itu secara tak terduga bermutasi. Ini berlaku untuk mutasi internal dan eksternal karena nilai yang dapat diubah dibagikan.NSMutableArray
variabel sudah cukup. Karena objek tidak pernah berhenti menjadi array yang dapat diubah, memanggil metode yang bermutasi padanya akan berhasil dan mengubah data yang dibagikan. Jika di sisi lain array yang dapat diubah asli disalin — mengubahnya ke array yang tidak dapat diubah - dan kemudian ditugaskan keNSMutableArray
variabel dan memiliki metode mutasi yang memanggilnya, panggilan tersebut akan gagal dengandoesNotRespondToSelector
kesalahan karena objek yang menerima panggilan metode mutasi ada di Bahkan tidak berubah dan tidak menanggapi metode-metode itu.Jika Anda membuat array melalui mutabilitas dan kemudian ingin mengembalikan versi yang tidak dapat diubah, Anda bisa mengembalikan array yang bisa diubah sebagai "NSArray" melalui pewarisan.
Jika Anda "mempercayai" penelepon untuk memperlakukan objek kembali (secara teknis masih bisa berubah) sebagai NSArray yang tidak berubah, ini adalah opsi yang lebih murah daripada
[mutableArray copy]
.Apple setuju:
Praktik di atas dibahas secara lebih rinci di sini:
Praktik Terbaik: Kembalikan mutableArray.copy atau mutableArray jika jenis kembali adalah NSArray
sumber
saya sedang mencari jawaban di swift 3 dan pertanyaan ini ditunjukkan sebagai hasil pertama dalam pencarian dan saya mendapatkan inspirasi jawabannya dari itu jadi di sini adalah kode 3 cepat
sumber