Yanıtlar:
objectForKey:
bir NSDictionary
yöntemdir. An NSDictionary
, birine benzer bir koleksiyon sınıfıdır NSArray
, dizinler kullanmak yerine öğeler arasında ayrım yapmak için anahtarlar kullanır. Anahtar, verdiğiniz rastgele bir dizedir. Hiçbir iki nesne aynı anahtara sahip olamaz (tıpkı bir içindeki iki nesne NSArray
aynı dizine sahip olamaz gibi).
valueForKey:
bir KVC yöntemidir. HERHANGİ bir sınıfla çalışır. valueForKey:
bir özelliğin adı için bir dize kullanarak erişmenize olanak tanır. Örneğin, Account
bir özelliği olan bir sınıf varsa accountNumber
, aşağıdakileri yapabilirim:
NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];
[newAccount setAccountNumber:anAccountNUmber];
NSNumber *anotherAccountNumber = [newAccount accountNumber];
KVC kullanarak, özelliği dinamik olarak erişebilirsiniz:
NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];
[newAccount setValue:anAccountNumber forKey:@"accountNumber"];
NSNumber *anotherAccountNumber = [newAccount valueForKey:@"accountNumber"];
Bunlar eşdeğer ifade kümeleridir.
Düşündüğünü biliyorum: vay, ama alaycı bir şekilde. KVC o kadar kullanışlı görünmüyor. Aslında, "wordy" görünüyor. Ancak çalışma zamanında bir şeyleri değiştirmek istediğinizde, diğer dillerde çok daha zor olan birçok harika şey yapabilirsiniz (ancak bu, sorunuzun kapsamının dışındadır).
KVC hakkında daha fazla bilgi edinmek istiyorsanız, özellikle Scott Stevenson'ın blogunda Google kullanıyorsanız birçok öğretici var . NSKeyValueCoding Protokol Başvurusu'na da göz atabilirsiniz .
Umarım yardımcı olur.
Ne zaman valueForKey:
bunu bir NSString vermek gerekir, oysa objectForKey:
herhangi bir NSObject alt sınıfı bir anahtar olarak alabilir. Bunun nedeni, Anahtar-Değer Kodlaması için, anahtarların her zaman dize olmasıdır.
Aslında, belgeler valueForKey:
bir NSString verdiğinizde bile objectForKey:
, dize bir ile başlamadığı sürece yine de çağıracağını @
belirtir, bu durumda çağırır [super valueForKey:]
ve bu durum valueForUndefinedKey:
bir istisna oluşturabilir.
objectForKey:
Mümkün olan her yerde kullanmak için harika bir neden valueForKey:
- valueForKey:
bilinmeyen bir anahtarla NSUnknownKeyException
"bu sınıf anahtar için kodlama ile uyumlu anahtar değer değil" diyecektir.
objectForKey:
Söylendiği gibi, veri tipi :(id)aKey
ise valueForKey:
veri tipidir :(NSString *)key
.
Örneğin:
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.
Yani, valueForKey:
sadece bir dize değeri alır ve bir KVC yöntemidir, oysa objectForKey:
herhangi bir nesne türünü alır.
İçindeki değere objectForKey
aynı türden bir nesne tarafından erişilir.
Burada kapsamlı bir cevap vermeye çalışacağım. Noktaların çoğu diğer cevaplarda ortaya çıkıyor, ancak her cevabı eksik buldum ve bazılarını yanlış buldum.
Birincisi ve en önemlisi, objectForKey:
bir olduğunu NSDictionary
iken, yöntem valueForKey:
NSDictionary dahil - hiçbir KVC şikayet sınıfının gerektirdiği bir KVC protokol yöntemidir.
@Dreamlax, dokümantasyon ipuçları yazdığı gibi Dahası, bu NSDictionary
onun uygulayan valueForKey:
yöntemi KULLANMA onun objectForKey:
uygulanmasını. Başka bir deyişle - [NSDictionary valueForKey:]
çağrılar [NSDictionary objectForKey:]
.
Bu valueForKey:
, hiçbir zaman objectForKey:
(aynı giriş anahtarında) daha hızlı olamaz , ancak kapsamlı testler yaptığım büyük bir NSDictionary milyarlarca rastgele erişim üzerinden yaklaşık% 5 ila% 15 fark anlamına gelir. Normal durumlarda - fark ihmal edilebilir.
Sonraki: KVC protokolü yalnızca NSString *
anahtarlarla çalışır , bu nedenle anahtar olarak valueForKey:
yalnızca bir NSString *
(veya alt sınıf) kabul ederken NSDictionary
, diğer nesne türleriyle anahtar olarak çalışabilir - böylece "alt seviye" objectForKey:
herhangi bir kopyalanabilir (NSCopying protokolü uyumlu) nesneyi kabul eder anahtar olarak.
Son olarak, NSDictionary's
uygulama valueForKey:
KVC'nin belgelerinde tanımlanan standart davranıştan sapar ve NSUnknownKeyException
bulamadığı bir anahtar için DEĞİLDİR - bu "özel" bir anahtar değilse - '@' ile başlayan - genellikle " toplama "işlev tuşu (örn. @"@sum, @"@avg"
). Bunun yerine, NSDictionary'de bir anahtar bulunamadığında bir sıfır döndürür - aynı şekilde davranırobjectForKey:
Notlarımı göstermek ve kanıtlamak için bazı test kodları aşağıdadır.
- (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);
}