Jawaban:
objectForKey:
adalah sebuah NSDictionary
metode. An NSDictionary
adalah kelas koleksi yang mirip dengan NSArray
, kecuali alih-alih menggunakan indeks, itu menggunakan kunci untuk membedakan antara item. Kunci adalah string acak yang Anda berikan. Tidak ada dua objek yang dapat memiliki kunci yang sama (sama seperti tidak ada dua objek dalam suatu NSArray
dapat memiliki indeks yang sama).
valueForKey:
adalah metode KVC. Ini bekerja dengan kelas APA SAJA. valueForKey:
memungkinkan Anda mengakses properti menggunakan string untuk namanya. Jadi misalnya, jika saya memiliki Account
kelas dengan properti accountNumber
, saya dapat melakukan hal berikut:
NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];
[newAccount setAccountNumber:anAccountNUmber];
NSNumber *anotherAccountNumber = [newAccount accountNumber];
Dengan menggunakan KVC, saya dapat mengakses properti secara dinamis:
NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];
[newAccount setValue:anAccountNumber forKey:@"accountNumber"];
NSNumber *anotherAccountNumber = [newAccount valueForKey:@"accountNumber"];
Itu adalah set pernyataan yang setara.
Saya tahu Anda berpikir: wow, tetapi dengan sarkastis. KVC tidak terlalu berguna. Bahkan, itu terlihat "bertele-tele". Tetapi ketika Anda ingin mengubah hal-hal saat runtime, Anda dapat melakukan banyak hal keren yang jauh lebih sulit dalam bahasa lain (tapi ini di luar ruang lingkup pertanyaan Anda).
Jika Anda ingin mempelajari lebih lanjut tentang KVC, ada banyak tutorial jika Anda Google terutama di blog Scott Stevenson . Anda juga dapat melihat Referensi Protokol NSKeyValueCoding .
Semoga itu bisa membantu.
Ketika Anda melakukannya, valueForKey:
Anda perlu memberinya NSString, sedangkan objectForKey:
dapat mengambil subkelas NSObject sebagai kunci. Ini karena untuk Pengodean Nilai-Kunci, kunci selalu berupa string.
Bahkan, dokumentasi menyatakan bahwa bahkan ketika Anda memberikan valueForKey:
NSString, ia objectForKey:
tetap akan memohon kecuali jika string dimulai dengan @
, dalam hal ini ia memanggil [super valueForKey:]
, yang dapat memanggil valueForUndefinedKey:
yang dapat menimbulkan pengecualian.
Berikut adalah alasan yang bagus untuk digunakan objectForKey:
sedapat mungkin alih-alih valueForKey:
- valueForKey:
dengan kunci yang tidak dikenal akan membuang kata NSUnknownKeyException
"kelas ini tidak sesuai dengan kode kunci untuk kunci".
Seperti yang dikatakan, objectForKey:
tipe data adalah :(id)aKey
sedangkan valueForKey:
tipe data :(NSString *)key
.
Sebagai contoh:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:@"123"],[NSNumber numberWithInteger:5], nil];
NSLog(@"objectForKey : --- %@",[dict objectForKey:[NSNumber numberWithInteger:5]]);
//This will work fine and prints ( 123 )
NSLog(@"valueForKey : --- %@",[dict valueForKey:[NSNumber numberWithInteger:5]]);
//it gives warning "Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'" ---- This will crash on runtime.
Jadi, valueForKey:
hanya akan mengambil nilai string dan merupakan metode KVC, sedangkan objectForKey:
akan mengambil semua jenis objek.
Nilai dalam objectForKey
akan diakses oleh jenis objek yang sama.
Saya akan mencoba memberikan jawaban yang komprehensif di sini. Sebagian besar poin muncul dalam jawaban lain, tetapi saya menemukan setiap jawaban tidak lengkap, dan beberapa salah.
Pertama dan terpenting, objectForKey:
adalah NSDictionary
metode, sedangkan valueForKey:
metode protokol KVC diperlukan dari setiap kelas keluhan KVC - termasuk NSDictionary.
Selanjutnya, seperti @dreamlax menulis, petunjuk dokumentasi yang NSDictionary
mengimplementasikan nya valueForKey:
metode MENGGUNAKAN nya objectForKey:
implementasi. Dengan kata lain - [NSDictionary valueForKey:]
panggilan [NSDictionary objectForKey:]
.
Ini menyiratkan, yang valueForKey:
tidak pernah bisa lebih cepat daripada objectForKey:
(pada tombol input yang sama) meskipun pengujian menyeluruh yang telah saya lakukan menyiratkan sekitar 5% hingga 15% perbedaan, lebih dari miliaran akses acak ke NSDictionary yang sangat besar. Dalam situasi normal - perbedaannya dapat diabaikan.
Berikutnya: Protokol KVC hanya berfungsi dengan NSString *
kunci, karenanya valueForKey:
hanya akan menerima kunci NSString *
(atau subkelas) sebagai kunci, sementara NSDictionary
dapat bekerja dengan jenis objek lain sebagai kunci - sehingga "level bawah" objectForKey:
menerima objek apa pun yang dapat disalin (sesuai protokol NSCopying) sebagai kunci.
Terakhir, NSDictionary's
implementasi penyimpangan dari valueForKey:
perilaku standar yang didefinisikan dalam dokumentasi KVC, dan TIDAK akan memancarkan NSUnknownKeyException
untuk kunci yang tidak dapat ditemukan - kecuali ini adalah kunci "khusus" - yang dimulai dengan '@' - yang biasanya berarti " kunci fungsi agregasi (misalnya @"@sum, @"@avg"
). Sebagai gantinya, itu hanya akan mengembalikan nol ketika kunci tidak ditemukan di NSDictionary - berperilaku sama denganobjectForKey:
Berikut ini adalah beberapa kode uji untuk menunjukkan dan membuktikan catatan saya.
- (void) dictionaryAccess {
NSLog(@"Value for Z:%@", [@{@"X":@(10), @"Y":@(20)} valueForKey:@"Z"]); // prints "Value for Z:(null)"
uint32_t testItemsCount = 1000000;
// create huge dictionary of numbers
NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:testItemsCount];
for (long i=0; i<testItemsCount; ++i) {
// make new random key value pair:
NSString *key = [NSString stringWithFormat:@"K_%u",arc4random_uniform(testItemsCount)];
NSNumber *value = @(arc4random_uniform(testItemsCount));
[d setObject:value forKey:key];
}
// create huge set of random keys for testing.
NSMutableArray *keys = [NSMutableArray arrayWithCapacity:testItemsCount];
for (long i=0; i<testItemsCount; ++i) {
NSString *key = [NSString stringWithFormat:@"K_%u",arc4random_uniform(testItemsCount)];
[keys addObject:key];
}
NSDictionary *dict = [d copy];
NSTimeInterval vtotal = 0.0, ototal = 0.0;
NSDate *start;
NSTimeInterval elapsed;
for (int i = 0; i<10; i++) {
start = [NSDate date];
for (NSString *key in keys) {
id value = [dict valueForKey:key];
}
elapsed = [[NSDate date] timeIntervalSinceDate:start];
vtotal+=elapsed;
NSLog (@"reading %lu values off dictionary via valueForKey took: %10.4f seconds", keys.count, elapsed);
start = [NSDate date];
for (NSString *key in keys) {
id obj = [dict objectForKey:key];
}
elapsed = [[NSDate date] timeIntervalSinceDate:start];
ototal+=elapsed;
NSLog (@"reading %lu objects off dictionary via objectForKey took: %10.4f seconds", keys.count, elapsed);
}
NSString *slower = (vtotal > ototal) ? @"valueForKey" : @"objectForKey";
NSString *faster = (vtotal > ototal) ? @"objectForKey" : @"valueForKey";
NSLog (@"%@ takes %3.1f percent longer then %@", slower, 100.0 * ABS(vtotal-ototal) / MAX(ototal,vtotal), faster);
}