2012-04-07 18 views
7

में गिनती का निरीक्षण करना, जब मैं गिनती, यानी अधिसूचित होना चाहता हूं। एनएसएआरएआरई परिवर्तनों में वस्तुओं की संख्या .. बेशक मुझे इसकी आवश्यकता नहीं होगी, अगर मैं सरणी में वस्तुओं को जोड़ने और हटाने के नियंत्रण में था। लेकिन मैं नहीं हूं, यह बिजनेस प्रोसेस मॉडल के संबंध में अप्रत्याशित रूप से होता है और बाहरी कारकों पर निर्भर करता है। क्या कोई साधारण सुरुचिपूर्ण समाधान है?एनएसएमयूटेबलएरे

संपादित करें: मैं निश्चित रूप से NSMutableArray को यह सही करने कर रहा हूँ ..

+0

मैं इस पर 100% नहीं हूं, लेकिन एक सरणी के लिए एक कीपैथ और प्रत्यय '@ count' इस मान को प्राप्त करने के लिए केवीसी तरीका है। तो शायद आप केवीओ 'सरणी @ गिनती' देख सकते हैं? https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/CollectionOperators.html#//apple_ref/doc/uid/20002176-BAJEAIEE – joerick

उत्तर

15

आप KVC का उपयोग करना होगा। लेकिन यह करने के बारे में कैसे जाना है? आखिरकार, एनएसएमयूटेबलएरे अपने उत्परिवर्तन विधियों या सामग्रियों के परिवर्तनों के लिए कुंजी-मूल्य-कोडिंग अनुपालन नहीं है। जवाब proxying है- एनएस subclassing [Mutable] ऐरे एक परेशानी का बहुत अधिक है।

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

@interface CFIKVCMutableArrayProxy : NSObject { 
    NSMutableArray *_innerArray; 
} 

- (NSUInteger)count; 

- (void)insertObject:(id)anObject atIndex:(NSUInteger)index; 
- (void)removeObjectAtIndex:(NSUInteger)index; 
- (void)addObject:(id)anObject; 
- (void)removeLastObject; 
- (void)insertObjects:(NSArray *)objects atIndexes:(NSIndexSet *)indexes; 
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; 

//… 

@end 

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

@implementation CFIKVCMutableArrayProxy 

//… 

- (NSUInteger)count { 
    return _innerArray.count; 
} 

- (void)addObject:(id)anObject { 
    [self willChangeValueForKey:@"count"]; 
    [_innerArray addObject:anObject]; 
    [self didChangeValueForKey:@"count"]; 
} 

- (void)removeLastObject { 
    [self willChangeValueForKey:@"count"]; 
    [_innerArray removeLastObject]; 
    [self didChangeValueForKey:@"count"]; 
} 

@end 

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

+0

कुछ समय बीत चुका है और एक भाग्यशाली सुधार होगा मेरे नियंत्रण से बाहर कोड के हिस्से पर लागू किया जाना चाहिए - मॉडल बदलते समय सरणी रखने वाली मुखौटा वस्तु अब NSNotifications जारी करेगी। आपका प्रस्तावित समाधान उल्लेखनीय है हालांकि आप छोटे लेकिन महत्वपूर्ण तथ्य को याद करते हैं कि मैं सरणी के नियंत्रण में नहीं था। तो मेरे लिए प्रॉक्सी ऑब्जेक्ट को सरणी के बजाय मुखौटा पर इंजेक्ट करना संभव नहीं था। –

+0

ज़रूरत से मैंने कुछ नया सीखा। – naz

+0

@ कोडाफ़ी स्पष्टीकरण के लिए धन्यवाद :) –

6

एक mutableArray एक में परिवर्तन का निरीक्षण

- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key 

जो द्वारा दिए गए अस्थायी प्रॉक्सी वस्तु का उपयोग करने की जरूरत है KVO अनुरूप है, यानी प्रॉक्सी वस्तु के किसी भी परिवर्तन भेजता इच्छा/सूचनाओं को बदलने किया।

निम्नलिखित डेमो वर्ग पूर्ण कार्यान्वयन

@interface DemoClass : NSObject 

@property (nonatomic) NSMutableArray *items; 

- (void)addItemsObserver:(id)object; 
- (void)removeItemsObserver:(id)object; 

@end 

@implementation DemoClass 

- (NSMutableArray *)items; 
{ 
    return [self mutableArrayValueForKey:@"_items"]; 
} 

- (void)addItemsObserver:(id)object 
{ 
    [self addObserver:object forKeyPath:@"[email protected]" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil]; 
} 

- (void)removeItemsObserver:(id)object 
{ 
    [self removeObserver:object forKeyPath:@"[email protected]" context:nil]; 
} 
@end 


@interface ObservingClass : NSObject 

@property (nonatomic) DemoClass *demoObject; 

@end 

@implementation ObservingClass 

- (instanstype)init 
{ 
    if (self = [super init]) { 
     _demoObject = [DemoClass new]; 

     [_demoObject addItemsObserver:self]; 
    } 
    return self; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath 
        ofObject:(id)object 
        change:(NSDictionary *)change 
        context:(void *)context 
{ 
    NSLog(@"is called on demoObject.items.count change"); 
} 

- (void)dealloc 
{ 
    [_demoObject removeItemsObserver:self]; 
} 

@end 

अब हर बार जब आप में जोड़ने के लिए या एक वस्तु को दूर से पता चला items आप कंसोल में नया लॉग देखेंगे (observeValueForKeyPath कहा जाता है)।

ऑटो-संश्लेषित ivar _items सरणी का कोई भी प्रत्यक्ष परिवर्तन कोई प्रभाव नहीं पड़ेगा।

यह भी ध्यान रखें कि आपको पर्यवेक्षक को [email protected] पर सेट करने की दृढ़ता से आवश्यकता है ([email protected] देखकर मूर्खतापूर्ण है)।

ध्यान दें कि आपको _items या self.items में प्रवेश करने की आवश्यकता नहीं है। यह दृश्य के पीछे किया जाएगा जब आप items गेटर कॉल करते हैं।

हर बार जब आप "सरणी" items बदलते हैं तो आपको नए पते के साथ नई वस्तु _items मिल जाएगी। लेकिन मैं इसे अभी भी items प्रॉक्सी गेटर के माध्यम से ढूंढ सकता हूं।

+0

आप 'removeProxyItemsObserver:' विधि भी चाह सकते हैं। –

+0

@AaronBrager, बस पूर्णता के लिए जोड़ा गया। धन्यवाद। – malex

संबंधित मुद्दे