खोज…


सबसे आम वास्तविक जीवन कुंजी मूल्य कोडिंग उदाहरण

कुंजी मान कोडिंग NSKeyValueCoding प्रोटोकॉल का उपयोग करके NSObject में एकीकृत है।

इसका क्या मतलब है?

इसका मतलब यह है कि कोई भी id ऑब्जेक्ट valueForKey मेथड और इसके विभिन्न वेरिएंट जैसे valueForKeyPhaar आदि को कॉल करने में सक्षम है।

इसका अर्थ यह भी है कि कोई भी आईडी ऑब्जेक्ट सेटवैल्यू पद्धति और उसके विभिन्न प्रकारों को भी लागू कर सकता है।

उदाहरण:

id obj = [[MyClass alloc] init];
id value = [obj valueForKey:@"myNumber"];

int myNumberAsInt = [value intValue];
myNumberAsInt = 53;
[obj setValue:@(myNumberAsInt) forKey:@"myNumber"];

अपवाद:

उपरोक्त उदाहरण मानता है कि MyClass में एक NSNumber प्रॉपर्टी है, जिसे MyNumber कहा जाता है। यदि MyNumber MyClass इंटरफ़ेस परिभाषा में प्रकट नहीं होता है, तो NSUndefinedKeyException को संभवतः दोनों लाइनों 2 और 5 पर उठाया जा सकता है - लोकप्रिय रूप से जाना जाता है:

this class is not key value coding-compliant for the key myNumber.

यह SO शक्तिशाली क्यों है:

आप उस वर्ग के गुणों की आवश्यकता के बिना कोड लिख सकते हैं जो किसी कक्षा के गुणों को गतिशील रूप से एक्सेस कर सकता है। इसका मतलब यह है कि एक तालिका दृश्य किसी NSObject व्युत्पन्न वस्तु के किसी भी गुण से मान प्रदर्शित कर सकता है, बशर्ते इसकी संपत्ति के नाम गतिशील रूप से रनटाइम पर आपूर्ति किए जाते हैं।

ऊपर दिए गए उदाहरण में, कोड माईक्लास के बिना भी काम कर सकता है और आईडी प्रकार obj को कॉलिंग कोड उपलब्ध है।

मुख्य मान

महत्वपूर्ण मान की स्थापना करना।

इस मामले में, हम ऐसी contentOffset का निरीक्षण करना चाहते हैं, जो हमारे पर्यवेक्षक के पास है

//
// Class to observe
//
@interface XYZScrollView: NSObject
@property (nonatomic, assign) CGPoint contentOffset;
@end

@implementation XYZScrollView
@end


//
// Class that will observe changes
//
@interface XYZObserver: NSObject
@property (nonatomic, strong) XYZScrollView *scrollView;
@end

@implementation XYZObserver

// simple way to create a KVO context
static void *XYZObserverContext = &XYZObserverContext;


// Helper method to add self as an observer to 
// the scrollView's contentOffset property
- (void)addObserver {

    // NSKeyValueObservingOptions
    //
    // - NSKeyValueObservingOptionNew
    // - NSKeyValueObservingOptionOld
    // - NSKeyValueObservingOptionInitial
    // - NSKeyValueObservingOptionPrior
    //
    // can be combined:
    // (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
    
    NSString *keyPath = NSStringFromSelector(@selector(contentOffset));
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew;    

    [self.scrollView addObserver: self 
                      forKeyPath: keyPath 
                         options: options
                         context: XYZObserverContext];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    
    if (context == XYZObserverContext) { // check the context

        // check the keyPath to see if it's any of the desired keyPath's.
        // You can observe multiple keyPath's
        if ([keyPath isEqualToString: NSStringFromSelector(@selector(contentOffset))]) {

            // change dictionary keys:
            // - NSKeyValueChangeKindKey
            // - NSKeyValueChangeNewKey
            // - NSKeyValueChangeOldKey
            // - NSKeyValueChangeIndexesKey
            // - NSKeyValueChangeNotificationIsPriorKey
            
            // the change dictionary here for a CGPoint observation will
            // return an NSPoint, so we can take the CGPointValue of it.
            CGPoint point = [change[NSKeyValueChangeNewKey] CGPointValue];
            
            // handle point
        }
        
    } else {

        // if the context doesn't match our current object's context
        // we want to pass the observation parameters to super
        [super observeValueForKeyPath: keyPath
                             ofObject: object
                               change: change
                              context: context];
    }
}

// The program can crash if an object is not removed as observer 
// before it is dealloc'd
//
// Helper method to remove self as an observer of the scrollView's
// contentOffset property
- (void)removeObserver {
    NSString *keyPath = NSStringFromSelector(@selector(contentOffset));
    [self.scrollView removeObserver: self forKeyPath: keyPath];
}

@end

केवीसी डेटा को छोड़कर

if ([[dataObject objectForKey:@"yourVariable"] isEqualToString:"Hello World"]) {
    return YES;
} else {
    return NO;
}

केवीसी का उपयोग करके संग्रहीत मूल्यों को आप जल्दी और आसानी से क्वेरी कर सकते हैं, उन्हें स्थानीय चर के रूप में पुनः प्राप्त करने या डालने की आवश्यकता के बिना।

संग्रह संचालक

संग्रह संचालकों का उपयोग "संग्रह-प्रकार" संपत्ति (यानी NSArray , NSSet और इसी तरह) पर एक ऑपरेशन करने के लिए KVC कुंजी पथ में किया जा सकता है। उदाहरण के लिए, प्रदर्शन करने के लिए एक सामान्य ऑपरेशन वस्तुओं को एक संग्रह में गिनना है। इसे प्राप्त करने के लिए, आप @count संग्रह ऑपरेटर का उपयोग करें:

self.array = @[@5, @4, @3, @2, @1];
NSNumber *count = [self.array valueForKeyPath:@"@count"];
NSNumber *countAlt = [self valueForKeyPath:@"array.@count"];
// count == countAlt == 5

हालांकि यह पूरी तरह से बेमानी है (हम सिर्फ count संपत्ति तक पहुंच सकते थे ), यह अवसर पर उपयोगी हो सकता है, हालांकि यह शायद ही कभी आवश्यक है। बहरहाल, कुछ संग्रह ऑपरेटरों कि और अधिक उपयोगी होते हैं अर्थात्, @max , @min , @sum , @avg और @unionOf परिवार। यह नोट करना महत्वपूर्ण है कि इन ऑपरेटर भी सही ढंग से कार्य करने के लिए ऑपरेटर निम्नलिखित एक अलग कुंजी पथ की आवश्यकता है। यहां उनकी एक सूची और उनके साथ काम करने वाले डेटा का प्रकार है:

ऑपरेटर डाटा प्रकार
@count (कोई नहीं)
@max NSNumber , NSDate , int (और संबंधित), आदि।
@min NSNumber , NSDate , int (और संबंधित), आदि।
@sum NSNumber , int (और संबंधित), double (और संबंधित), आदि।
@avg NSNumber , int (और संबंधित), double (और संबंधित), आदि।
@unionOfObjects NSArray , NSSet , आदि।
@distinctUnionOfObjects NSArray , NSSet , आदि।
@unionOfArrays NSArray<NSArray*>
@distinctUnionOfArrays NSArray<NSArray*>
@distinctUnionOfSets NSSet<NSSet*>

@max और @min संग्रह में वस्तुओं की संपत्ति के क्रमशः उच्चतम या निम्नतम मान लौटाएगा। उदाहरण के लिए, निम्नलिखित कोड देखें:

// “Point” class used in our collection
@interface Point : NSObject

@property NSInteger x, y;

+ (instancetype)pointWithX:(NSInteger)x y:(NSInteger)y;

@end

...

self.points = @[[Point pointWithX:0 y:0],
                [Point pointWithX:1 y:-1],
                [Point pointWithX:5 y:-6],
                [Point pointWithX:3 y:0],
                [Point pointWithX:8 y:-4],
];

NSNumber *maxX = [self valueForKeyPath:@"[email protected]"];
NSNumber *minX = [self valueForKeyPath:@"[email protected]"];
NSNumber *maxY = [self valueForKeyPath:@"[email protected]"];
NSNumber *minY = [self valueForKeyPath:@"[email protected]"];

NSArray<NSNumber*> *boundsOfAllPoints = @[maxX, minX, maxY, minY];

...

कोड और शुद्ध फाउंडेशन की सिर्फ 4 पंक्तियों में, की-वैल्यू कोडिंग संग्रह ऑपरेटरों की शक्ति के साथ हम एक आयत निकालने में सक्षम थे जो हमारे सरणी के सभी बिंदुओं को इनकैप्सुलेट करता है।

यह ध्यान रखना महत्वपूर्ण है कि इन तुलनाओं को वस्तुओं पर compare: विधि को लागू करके बनाया जाता है, इसलिए यदि आप कभी भी इन ऑपरेटरों के साथ अपनी खुद की कक्षा बनाना चाहते हैं, तो आपको इस पद्धति को लागू करना होगा।

@sum , जैसा कि आप शायद अनुमान लगा सकते हैं, एक संपत्ति के सभी मूल्यों को जोड़ सकते हैं।

@interface Expense : NSObject

@property NSNumber *price;

+ (instancetype)expenseWithPrice:(NSNumber *)price;

@end

...

self.expenses = @[[Expense expenseWithPrice:@1.50],
                  [Expense expenseWithPrice:@9.99],
                  [Expense expenseWithPrice:@2.78],
                  [Expense expenseWithPrice:@9.99],
                  [Expense expenseWithPrice:@24.95]
];

NSNumber *totalExpenses = [self valueForKeyPath:@"[email protected]"];

यहाँ, हमने सरणी में सभी खर्चों की कुल कीमत का पता लगाने के लिए @sum का उपयोग किया। यदि हम इसके बजाय प्रत्येक कीमत के लिए भुगतान की जाने वाली औसत कीमत का पता लगाना चाहते हैं, तो हम @avg उपयोग कर सकते हैं:

NSNumber *averagePrice = [self valueForKeyPath:@"[email protected]"];

अंत में, @unionOf परिवार है। इस परिवार में पांच अलग-अलग ऑपरेटर हैं, लेकिन वे सभी एक ही काम करते हैं, जिनमें से प्रत्येक के बीच केवल छोटे अंतर हैं। सबसे पहले, वहाँ @unionOfObjects जो एक सरणी में वस्तुओं के गुणों की एक सरणी लौटाएगा:

// See "expenses" array above

NSArray<NSNumber*> *allPrices = [self valueForKeyPath:
    @"[email protected]"];

// Equal to @[ @1.50, @9.99, @2.78, @9.99, @24.95 ]

@distinctUnionOfObjects कार्यों के रूप में ही @unionOfObjects , लेकिन यह डुप्लिकेट निकालता है:

NSArray<NSNumber*> *differentPrices = [self valueForKeyPath:
    @"[email protected]"];

// Equal to @[ @1.50, @9.99, @2.78, @24.95 ]

और अंत में, @unionOf परिवार में अंतिम 3 संचालक एक कदम गहराई तक जाएंगे और एक संपत्ति के लिए पाए गए मानों की एक सरणी @unionOf , जो @unionOf -नेस्टेड ऐरे के अंदर निहित हैं:

NSArray<NSArray<Expense*,Expense*>*> *arrayOfArrays =
    @[
        @[ [Expense expenseWithPrice:@19.99],
           [Expense expenseWithPrice:@14.95],
           [Expense expenseWithPrice:@4.50],
           [Expense expenseWithPrice:@19.99]
         ],

        @[ [Expense expenseWithPrice:@3.75],
           [Expense expenseWithPrice:@14.95]
         ]
     ];

// @unionOfArrays
NSArray<NSNumber*> allPrices = [arrayOfArrays valueForKeyPath:
    @"@unionOfArrays.price"];
// Equal to @[ @19.99, @14.95, @4.50, @19.99, @3.75, @14.95 ];

// @distinctUnionOfArrays
NSArray<NSNumber*> allPrices = [arrayOfArrays valueForKeyPath:
    @"@distinctUnionOfArrays.price"];
// Equal to @[ @19.99, @14.95, @4.50, @3.75 ];

इस उदाहरण से गायब होने वाला @distinctUnionOfSets , हालाँकि यह ठीक @distinctUnionOfArrays के समान है, लेकिन इसके साथ काम करता है और NSSet लौटाता है (कोई distinct संस्करण नहीं है क्योंकि एक सेट में, प्रत्येक वस्तु को वैसे भी अलग होना चाहिए)।

और बस! यदि सही ढंग से उपयोग किया जाता है तो संग्रह ऑपरेटर वास्तव में शक्तिशाली हो सकते हैं, और अनावश्यक रूप से सामान के माध्यम से लूप से बचने में मदद कर सकते हैं।

एक अंतिम नोट: आप NSNumber s (अतिरिक्त प्रॉपर्टी एक्सेस के बिना) के सरणियों पर मानक संग्रह ऑपरेटरों का भी उपयोग कर सकते हैं। ऐसा करने के लिए, आप self -छद्म संपत्ति का उपयोग करते हैं जो केवल वस्तु लौटाता है:

NSArray<NSNumber*> *numbers = @[@0, @1, @5, @27, @1337, @2048];

NSNumber *largest = [numbers valueForKeyPath:@"@max.self"];
NSNumber *smallest = [numbers valueForKeyPath:@"@min.self"];
NSNumber *total = [numbers valueForKeyPath:@"@sum.self"];
NSNumber *average = [numbers valueForKeyPath:@"@avg.self"];


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow