ObjectForKey और valueForKey के बीच अंतर?


345

बीच क्या अंतर है objectForKeyऔर valueForKey? मैंने प्रलेखन में दोनों को देखा और वे मुझे समान लगे।

जवाबों:


403

objectForKey:एक NSDictionaryविधि है। एक NSDictionaryएक के समान एक संग्रह वर्ग है NSArray, बजाय अनुक्रमणिका का उपयोग कर के अलावा, यह कुंजी का उपयोग करता है आइटम के बीच अंतर करने के लिए। एक कुंजी एक मनमाना स्ट्रिंग है जो आप प्रदान करते हैं। किसी भी दो वस्तुओं में एक ही कुंजी नहीं हो सकती है (जिस तरह एक में दो वस्तुओं में एक NSArrayही सूचकांक नहीं हो सकता है)।

valueForKey:KVC विधि है। यह किसी भी वर्ग के साथ काम करता है। valueForKey:आपको इसके नाम के लिए एक स्ट्रिंग का उपयोग करके एक संपत्ति का उपयोग करने की अनुमति देता है। उदाहरण के लिए, यदि मेरे पास Accountसंपत्ति के साथ एक वर्ग है , तो मैं accountNumberनिम्नलिखित कर सकता हूं:

NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];

[newAccount setAccountNumber:anAccountNUmber];

NSNumber *anotherAccountNumber = [newAccount accountNumber];

KVC का उपयोग करके, मैं संपत्ति को गतिशील रूप से एक्सेस कर सकता हूं:

NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];

[newAccount setValue:anAccountNumber forKey:@"accountNumber"];

NSNumber *anotherAccountNumber = [newAccount valueForKey:@"accountNumber"];

वे बयानों के समतुल्य सेट हैं।

मुझे पता है कि आप सोच रहे हैं: वाह, लेकिन व्यंग्यात्मक रूप से। KVC यह सब उपयोगी नहीं दिखता है। वास्तव में, यह "वर्डी" दिखता है। लेकिन जब आप रनटाइम में चीजों को बदलना चाहते हैं, तो आप बहुत सारी शांत चीजें कर सकते हैं जो अन्य भाषाओं में बहुत अधिक कठिन हैं (लेकिन यह आपके प्रश्न के दायरे से बाहर है)।

यदि आप केवीसी के बारे में अधिक जानना चाहते हैं, तो कई ट्यूटोरियल हैं यदि आप विशेष रूप से स्कॉट स्टीवेन्सन के ब्लॉग पर Google । आप NSKeyValueCoding प्रोटोकॉल संदर्भ भी देख सकते हैं ।

उम्मीद है की वो मदद करदे।


12
valueForKey एनएसडॉर वस्तुओं के लिए अलग तरह से व्यवहार करता है जो इस बात पर निर्भर करता है कि कुंजी @ प्रतीक से शुरू होती है या नहीं।
ड्रीमलैक्स

61
objectForKey: किसी भी ऑब्जेक्ट को कुंजी के रूप में स्वीकार करता है, न कि केवल स्ट्रिंग्स पर। केवल आवश्यकता यह है कि कुंजी NSCopying प्रोटोकॉल का समर्थन करती है।
एशले क्लार्क

5
मुझे आश्चर्य है कि किसी ने भी इस उत्तर को सही नहीं बताया है। मूल्य: तकनीकी रूप से आपको संबंधित उदाहरण चर तक पहुंच नहीं देता है, बल्कि पहुंच विधि है जो कि (उदाहरण के लिए) चर का प्रबंधन कर सकती है।
दानी जौमा

7
चेतावनी: valueForKey तीव्रता से धीमा हो सकता है - यह वर्तमान में मेरे iPad ऐप में एक बड़ी अड़चन है, इतना धीमा कि इसे "मानक" शब्दकोश के साथ बदलने से एप्लिकेशन को विशेष रूप से तेजी से बनाया गया। IOS पर KVC के साथ कुछ बहुत गलत है, और मैं इसे फिर कभी उपयोग नहीं करूंगा - प्रदर्शन में गिरावट के लायक नहीं, और वैसे भी इसे फिर से लिखना होगा। यह NSString कुंजियों का उपयोग CALYers पर NSString मानों के साथ कर रहा था। इंस्ट्रूमेंट से पता चला कि "CAObject_valueForKey" कुल रनटाइम का 25% था (!)
एडम

2
@ अदम जो डरावना लगता है। क्या आपने iOS7 के बाद से इसे फिर से आजमाया है? यदि हां, तो क्या चीजें बदल गई हैं?
अनहिलिग

64

जब आपको valueForKey:इसकी आवश्यकता होती है तो आप इसे NSString दे objectForKey:सकते हैं , जबकि किसी भी NSObject उपवर्ग को एक कुंजी के रूप में ले सकते हैं। ऐसा इसलिए है क्योंकि की-वैल्यू कोडिंग के लिए, चाबियाँ हमेशा तार होती हैं।

वास्तव में, प्रलेखन में कहा गया है कि जब आप valueForKey:एक एनएसएसट्रिंग देते हैं, objectForKey:तब भी यह वैसे ही आह्वान करेगा जब तक कि स्ट्रिंग एक के साथ शुरू नहीं होती है @, जिस स्थिति में यह आह्वान करता है [super valueForKey:], जो valueForUndefinedKey:कि एक अपवाद को बढ़ा सकता है।


क्या आप कृपया मुझे आपके द्वारा दिए गए दस्तावेज़ का लिंक दे सकते हैं। धन्यवाद।
अली अमीन

5
@ عليامين: यह यहीं
dreamlax

20

यहां एक objectForKey:संभव कारण का उपयोग करने के बजाय एक महान कारण है valueForKey:- valueForKey:एक अज्ञात कुंजी के साथ NSUnknownKeyExceptionयह कहते हुए फेंक देगा कि "यह वर्ग कुंजी के लिए महत्वपूर्ण मूल्य कोडिंग-अनुरूप नहीं है"।


5
यह जानना अच्छा है कि "valueForKey: अज्ञात कुंजी के साथ NSUnognKeyException को फेंक देंगे," यह वर्ग कुंजी के लिए महत्वपूर्ण मान कोडिंग-अनुपालन नहीं है "
onmyway133

यह एनएसबॉडी के साथ बस सच नहीं है, और आप इस कोशिश में आपका स्वागत करते हैं: NSLog (@ "Z:% @", [@ {@ "X": @ (10), @ "Y": @ (20)} valueForKey: @ "Z"]); valueForKey अन्य वर्गों पर ऐसे अपवादों का उत्सर्जन करेगा जो एक निर्दिष्ट कुंजी का समर्थन नहीं करते हैं - लेकिन NS सहकर्मी उपवर्गों के लिए - आपको बस एक शांत शून्य प्राप्त होगा। इसे
आज़माइए

13

जैसा कि कहा गया है, objectForKey:डेटाटाइप है :(id)aKeyजबकि valueForKey:डेटाटाइप है :(NSString *)key

उदाहरण के लिए:

 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. 

तो, valueForKey:केवल एक स्ट्रिंग मान लेगा और एक केवीसी विधि है, जबकि objectForKey:किसी भी प्रकार की वस्तु ले जाएगा।

मूल्य objectForKeyको उसी तरह के ऑब्जेक्ट द्वारा एक्सेस किया जाएगा।


0

मैं यहाँ एक व्यापक उत्तर देने की कोशिश करूँगा। अधिकांश बिंदु अन्य उत्तरों में दिखाई देते हैं, लेकिन मैंने प्रत्येक उत्तर को अधूरा पाया, और कुछ गलत।

सबसे पहले और सबसे महत्वपूर्ण, objectForKey:एक NSDictionaryविधि है, जबकिvalueForKey: केवीसी शिकायत वर्ग के लिए आवश्यक एक केवीसी प्रोटोकॉल विधि है - जिसमें एनएसडीआई भी शामिल है।

इसके अलावा, @dreamlax के रूप में लिखा था, प्रलेखन संकेत है कि NSDictionaryइसके लागू करता है valueForKey:विधि का उपयोग कर अपने objectForKey:कार्यान्वयन। दूसरे शब्दों में - [NSDictionary valueForKey:]पर कॉल करता है[NSDictionary objectForKey:]

इसका तात्पर्य यह है कि इससे valueForKey:तेज कभी नहीं हो सकताobjectForKey: (एक ही इनपुट कुंजी पर) हालांकि पूरी तरह से परीक्षण मैंने लगभग 5% से 15% अंतर के साथ किया है, अरबों से अधिक विशाल पहुंच के लिए यादृच्छिक पहुंच पर। सामान्य स्थितियों में - अंतर नगण्य है।

अगला: केवीसी प्रोटोकॉल केवल NSString *कुंजी के साथ काम करता है , इसलिए valueForKey:केवल NSString *कुंजी के रूप में (या उपवर्ग) को स्वीकार करेगा , जबकि कुंजी के रूप में NSDictionaryअन्य प्रकार की वस्तुओं के साथ काम कर सकता है - ताकि "निचला स्तर" objectForKey:किसी भी कॉपी-सक्षम (NSCopying प्रोटोकॉल अनुरूप) को स्वीकार कर ले। कुंजी के रूप में।

अंतिम, केवीसी के प्रलेखन में परिभाषित मानक व्यवहार से विचलन का NSDictionary'sकार्यान्वयन valueForKey:, और NSUnknownKeyExceptionयह एक कुंजी के लिए उत्सर्जन नहीं करेगा जो इसे नहीं मिल सकता है - जब तक कि यह "विशेष" कुंजी नहीं है - जो कि '@' से शुरू होता है - जिसका आमतौर पर मतलब है " एकत्रीकरण "फ़ंक्शन कुंजी (जैसे @"@sum, @"@avg")। इसके बजाय, यह एनएसएल में एक कुंजी नहीं मिलने पर बस एक शून्य लौटाएगा - जैसा व्यवहार करनाobjectForKey:

मेरे नोट्स को प्रदर्शित करने और साबित करने के लिए कुछ परीक्षण कोड निम्नलिखित हैं।

- (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);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.