Saya mencari idiom standar untuk beralih ke NSArray. Kode saya harus cocok untuk OS X 10.4+.
sumber
Saya mencari idiom standar untuk beralih ke NSArray. Kode saya harus cocok untuk OS X 10.4+.
Kode yang umumnya lebih disukai untuk 10,5 + / iOS.
for (id object in array) {
// do something with object
}
Konstruk ini digunakan untuk menghitung objek dalam koleksi yang sesuai dengan NSFastEnumeration
protokol. Pendekatan ini memiliki keunggulan kecepatan karena menyimpan pointer ke beberapa objek (diperoleh melalui pemanggilan metode tunggal) dalam buffer dan beralih melalui mereka dengan memajukan melalui buffer menggunakan aritmatika pointer. Ini jauh lebih cepat daripada memanggil -objectAtIndex:
setiap kali melalui loop.
Perlu juga dicatat bahwa sementara Anda secara teknis dapat menggunakan for-in loop untuk melangkah melalui NSEnumerator
, saya telah menemukan bahwa ini membatalkan hampir semua keuntungan kecepatan enumerasi cepat. Alasannya adalah bahwa NSEnumerator
implementasi default -countByEnumeratingWithState:objects:count:
hanya menempatkan satu objek di buffer pada setiap panggilan.
Saya melaporkan ini dalam radar://6296108
(Pencacahan Cepat NSEnumerator lamban) tetapi dikembalikan sebagai Tidak Akan Diperbaiki. Alasannya adalah bahwa penghitungan cepat pra-mengambil sekelompok objek, dan jika Anda ingin menghitung hanya ke titik tertentu dalam pencacah (misalnya sampai objek tertentu ditemukan, atau kondisi terpenuhi) dan menggunakan pencacah yang sama setelah keluar dari loop, akan sering terjadi bahwa beberapa objek akan dilewati.
Jika Anda mengkodekan untuk OS X 10.6 / iOS 4.0 dan di atasnya, Anda juga memiliki opsi untuk menggunakan API berbasis blok untuk menghitung array dan koleksi lainnya:
[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
// do something with object
}];
Anda juga dapat menggunakan -enumerateObjectsWithOptions:usingBlock:
dan meneruskan NSEnumerationConcurrent
dan / atau NSEnumerationReverse
sebagai argumen opsi.
Idi standar untuk pra-10.5 adalah dengan menggunakan NSEnumerator
loop sementara, seperti:
NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
// do something with object
}
Saya sarankan menjaganya agar tetap sederhana. Mengikat diri sendiri ke jenis array tidak fleksibel, dan peningkatan kecepatan yang diklaim -objectAtIndex:
tidak signifikan terhadap peningkatan dengan penghitungan cepat pada 10,5+. (Penghitungan cepat sebenarnya menggunakan pointer aritmatika pada struktur data yang mendasarinya, dan menghapus sebagian besar overhead metode panggilan.) Optimalisasi prematur tidak pernah merupakan ide yang baik - ini menghasilkan kode yang lebih berantakan untuk menyelesaikan masalah yang bukan merupakan hambatan Anda.
Saat menggunakan -objectEnumerator
, Anda sangat mudah mengubah ke koleksi enumerable lain (seperti NSSet
, kunci dalam NSDictionary
, dll.), Atau bahkan beralih ke -reverseObjectEnumerator
untuk menghitung sebuah array mundur, semua tanpa perubahan kode lainnya. Jika kode iterasi adalah dalam metode, Anda bahkan bisa lulus dalam setiap NSEnumerator
dan kode bahkan tidak harus peduli tentang apa itu iterasi. Lebih lanjut, sebuah NSEnumerator
(setidaknya yang disediakan oleh kode Apple) mempertahankan koleksi yang disebutkan selama ada lebih banyak objek, jadi Anda tidak perlu khawatir tentang berapa lama objek autoreleased akan ada.
Mungkin hal terbesar yang NSEnumerator
(atau penghitungan cepat) melindungi Anda dari adalah memiliki koleksi yang dapat berubah (array atau lainnya) berubah di bawah Anda tanpa sepengetahuan Anda saat Anda menghitungnya. Jika Anda mengakses objek berdasarkan indeks, Anda bisa mengalami pengecualian aneh atau kesalahan satu per satu (seringkali lama setelah masalah terjadi) yang bisa mengerikan untuk debug. Pencacahan menggunakan salah satu idiom standar memiliki perilaku "gagal-cepat", sehingga masalah (disebabkan oleh kode yang salah) akan segera muncul ketika Anda mencoba mengakses objek berikutnya setelah mutasi terjadi. Ketika program menjadi lebih kompleks dan multi-utas, atau bahkan bergantung pada sesuatu yang dapat dimodifikasi oleh kode pihak ketiga, kode enumerasi yang rapuh menjadi semakin bermasalah. Enkapsulasi dan abstraksi FTW! :-)
for (id object in array)
, apakah ada cara untuk juga menentukan objek indeks saat ini dalam array, atau apakah penghitung terpisah perlu dimasukkan?for
loop seperti ini:for(;;) { id object = [ e nextObject ] ; if ( !e ) { break ; } ... your loop operation ... }
Untuk OS X 10.4.x dan sebelumnya:
Untuk OS X 10.5.x (atau iPhone) dan lebih tinggi:
sumber
for (NSUInteger i = 0, count = [myArray count]; i < count; i++)
mungkin yang paling efisien dan ringkas yang akan Anda dapatkan untuk pendekatan ini.Hasil tes dan kode sumber di bawah ini (Anda dapat mengatur jumlah iterasi dalam aplikasi). Waktunya dalam milidetik, dan setiap entri adalah hasil rata-rata menjalankan tes 5-10 kali. Saya menemukan bahwa umumnya akurat untuk 2-3 digit signifikan dan setelah itu akan bervariasi setiap kali dijalankan. Itu memberikan margin kesalahan kurang dari 1%. Tes berjalan pada iPhone 3G karena itulah platform target yang saya minati.
Kelas-kelas yang disediakan oleh Cocoa untuk menangani set data (NSDictionary, NSArray, NSSet dll.) Menyediakan antarmuka yang sangat bagus untuk mengelola informasi, tanpa harus khawatir tentang birokrasi manajemen memori, realokasi, dll. . Saya pikir itu cukup jelas bahwa mengatakan menggunakan NSArray dari NSNumber akan lebih lambat daripada C Array float untuk iterasi sederhana, jadi saya memutuskan untuk melakukan beberapa tes, dan hasilnya cukup mengejutkan! Saya tidak berharap ini akan seburuk ini. Catatan: tes ini dilakukan pada iPhone 3G karena itulah platform target yang saya minati.
Dalam tes ini saya melakukan perbandingan kinerja akses acak yang sangat sederhana antara C float * dan NSArray dari NSNumbers
Saya membuat loop sederhana untuk meringkas isi dari setiap array dan mengatur waktu menggunakan mach_absolute_time (). NSMutableArray memakan waktu rata-rata 400 kali lebih lama !! (bukan 400 persen, hanya 400 kali lebih lama! itu 40.000% lebih lama!).
Tajuk:
// Array_Speed_TestViewController.h
// Tes Kecepatan Array
// Dibuat oleh Mehmet Akten pada 05/02/2009.
// Hak cipta MSA Visuals Ltd. 2009. Hak cipta dilindungi undang-undang.
Penerapan:
// Array_Speed_TestViewController.m
// Tes Kecepatan Array
// Dibuat oleh Mehmet Akten pada 05/02/2009.
// Hak cipta MSA Visuals Ltd. 2009. Hak cipta dilindungi undang-undang.
Dari: memo.tv
////////////////////
Tersedia sejak pengenalan blok, ini memungkinkan untuk mengulangi array dengan blok. Sintaksnya tidak sebagus pencacahan cepat, tetapi ada satu fitur yang sangat menarik: pencacahan serentak. Jika urutan enumerasi tidak penting dan pekerjaan dapat dilakukan secara paralel tanpa mengunci, ini dapat memberikan peningkatan yang cukup besar pada sistem multi-core. Lebih lanjut tentang itu di bagian enumerasi bersamaan.
/////////// NSFastEnumerator
Gagasan di balik penghitungan cepat adalah menggunakan akses array C cepat untuk mengoptimalkan iterasi. Tidak hanya itu seharusnya lebih cepat daripada NSEnumerator tradisional, tetapi Objective-C 2.0 juga menyediakan sintaksis yang sangat ringkas.
/////////////////
NSEnumerator
Ini adalah bentuk iterasi eksternal: [myArray objectEnumerator] mengembalikan objek. Objek ini memiliki metode nextObject yang dapat kita panggil secara berulang sampai mengembalikan nihil
/////////////////
objectAtIndex: enumeration
Menggunakan for for yang meningkatkan bilangan bulat dan menanyakan objek menggunakan [myArray objectAtIndex: index] adalah bentuk paling dasar dari enumerasi.
////////////// Dari: darkdust.net
sumber
Tiga cara tersebut adalah:
sumber
Tambahkan
each
metode di AndaNSArray category
, Anda akan membutuhkannyaKode diambil dari ObjectiveSugar
sumber
Inilah cara Anda mendeklarasikan serangkaian string dan beralihinya:
sumber
Untuk Swift
sumber
Melakukan hal ini :-
sumber