2012-09-03 21 views
10

मैं एक कक्षा एक्सटेंशन में UITableView में कोई प्रॉपर्टी जोड़ते चाहते हैं:आईओएस वर्ग विस्तार में एक संपत्ति की परिभाषा

@interface UITableViewController() 

@property NSString *entityString; 

@end 

तब मैं एक्सटेंशन आयात और फिर मैं UITableViewController का एक उपवर्ग में entityString संपत्ति का उपयोग करें:

@implementation CustomerTableViewController 

- (void)viewDidLoad { 
    self.entityString = @"Customer"; 
    ... 
    [super viewDidLoad]; 
} 
... 

Apple documentation का कहना है:

the compiler will automatically synthesize the relevant accessor methods (...) inside the primary class implementation.

लेकिन जब मैं पूर्व करने की कोशिश इसे समझें मुझे यह त्रुटि मिलती है:

-[CustomerTableViewController setEntityString:]: unrecognized selector sent to instance 0x737b670

मैं क्या गलत कर रहा हूं? शायद संपत्ति subclasses द्वारा पहुंचा जा सकता है?

उत्तर

5

एक वर्ग विस्तार अतिरिक्त इंटरफ़ेस घोषित करने के लिए प्रयोग किया जाता है - तरीकों और गुण - जिसका कार्यान्वयन अनुबंध वर्ग के प्राथमिक @implementaiton भीतर पूरी की जाएगी।

यही कारण है कि आप भंडारण को जोड़ नहीं सकते - एक वर्ग एक्सटेंशन के माध्यम से ivars जोड़ें। एक वर्ग विस्तार एक इंटरफ़ेस है, और नहीं, कम नहीं। @synthesize@property घोषणाओं के लिए भंडारण बनाता है, लेकिन @property कक्षा के @implementation में दिखाई दे सकता है (चाहे स्पष्ट रूप से या संकलक के डिफ़ॉल्ट व्यवहार के रूप में)।

चूंकि आप ढांचे वर्ग को पुन: संकलित नहीं कर सकते हैं, इसलिए आप इसमें इवर नहीं जोड़ सकते हैं।

@ प्रशांत का उत्तर मौजूदा वर्ग में संग्रहण जोड़ने का एक तरीका है। हालांकि, उस मार्ग पर जाना आम तौर पर अवांछनीय है; फ्रेमवर्क कक्षाओं से लटका राज्य बंद willy-nilly खराब डिजाइन का संकेत है और समय के साथ बनाए रखने के लिए आपके आवेदन को और अधिक कठिन बना देगा।

अपने डिज़ाइन पर फिर से विचार करने के लिए बेहतर है, समझें कि आपको वर्तमान में उस ऑब्जेक्ट को राज्य संलग्न करने की आवश्यकता क्यों है जिसमें सीधे इसे शामिल नहीं किया जा सकता है, और उस आवश्यकता को दोबारा सुधारना।

+0

को सही करने के लिए धन्यवाद bbum कक्षा विस्तार में जोड़ा जा रहा है या यह इस्तेमाल किए गए कंपाइलर पर निर्भर करता है? – tiguero

+3

आप कक्षा एक्सटेंशन में ivars और गुणों की घोषणा कर सकते हैं, लेकिन इस तरह के संग्रहण को तब तक नहीं बनाया जाएगा जब तक कि कक्षा के @ कार्यान्वयन के संकलन से पहले संकलक द्वारा एक्सटेंशन को देखा न जाए। – bbum

+0

स्पष्टीकरण के लिए धन्यवाद - मुझे नहीं पता था कि अलाज़रो वास्तव में एक फ्रेमवर्क कक्षा के लिए कक्षा विस्तार का उपयोग कर रहा था – tiguero

4

डॉक्स राज्य:

Class extensions are like anonymous categories, except that the methods they declare must be implemented in the main @implementation block for the corresponding class.

जब आप @property उपयोग करें, यह मोटे तौर पर घोषित एक्सेसर तरीकों के बराबर है। तो इसका मतलब है कि आप केवल ऐसी चीज ही कर सकते हैं यदि आप वर्ग के "मुख्य" @implementation ब्लॉक के लेखक भी हैं, जो UITableViewController के साथ हैं, तो आप नहीं हैं।

यहां आपका एकमात्र विकल्प श्रेणियां है, जो आवृत्ति चर जोड़ नहीं सकता है।

The docs link, और उस पृष्ठ के आखिरी लाइन पर ध्यान दें:

The implementation of the setValue: method must appear within the main @implementation block for the class (you cannot implement it in a category). If this is not the case, the compiler emits a warning that it cannot find a method definition for setValue:.

+0

मुझे लगता है कि यह मेरा मामला नहीं है, मैं एक ivar + accessors का उपयोग नहीं कर रहा हूं। हालांकि, संकलक मेरे कोड के बारे में शिकायत नहीं करता है। त्रुटि रनटाइम में है। – alazaro

+3

एक '@ संपत्ति' ** ** एक ivar प्लस एक्सेसर्स है। –

+0

हाँ, मुझे पता है, लेकिन संकलक आपके लिए काम करता है। मैंने सोचा कि यह मुख्य वर्ग में भी एक्सेसर्स जोड़ सकता है, इससे कोई फर्क नहीं पड़ता कि यह मेरे लिए है या नहीं। – alazaro

12

बजाय साहचर्य संदर्भ के साथ एक वर्ग का उपयोग करें। यह बहुत साफ है और UIButton के सभी उदाहरणों पर काम करेगा।

UIButton+Property.h 

#import <Foundation/Foundation.h> 

@interface UIButton(Property) 

@property (nonatomic, retain) NSObject *property; 

@end 


UIButton+Property.m 

#import "UIButton+Property.h" 
#import <objc/runtime.h> 

@implementation UIButton(Property) 

static char UIB_PROPERTY_KEY; 

@dynamic property; 

-(void)setProperty:(NSObject *)property 
{ 
    objc_setAssociatedObject(self, &UIB_PROPERTY_KEY, property, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

-(NSObject*)property 
{ 
    return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY); 
} 

@end 

// उदाहरण उपयोग

#import "UIButton+Property.h" 


UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
button1.property = @"HELLO"; 
NSLog(@"Property %@", button1.property); 
button1.property = nil; 
NSLog(@"Property %@", button1.property); 
+0

कक्षा विस्तार से एसोसिएटिव संदर्भ क्लीनर कैसे हैं? – vikingosegundo

+4

वे क्लीनर हैं क्योंकि वे काम करते हैं (कक्षा विस्तार इसलिए नहीं है क्योंकि जब कक्षा के लिए कार्यान्वयन को संकलित किया गया था तब एक्सटेंशन मौजूद नहीं था), लेकिन इससे उन्हें साफ नहीं किया जाता है। मौजूदा ढांचे वर्गों में राज्य जोड़ना खराब डिजाइन और उच्च नाजुकता का संकेत है। जबकि प्रशांत का जवाब काम करता है, ऐसा करना आम तौर पर एक संकेत है कि आपको अपने वास्तुकला पर पुनर्विचार करना चाहिए। – bbum

+0

उस कोड में '@ गतिशील 'का उपयोग करने की कोई आवश्यकता नहीं है, btw। – bbum