2011-03-21 28 views
6

यदि मैं कस्टम UIView सबक्लास को परिभाषित करना चाहता हूं जो इसकी सीमाओं को सेट करते समय कुछ करता है, तो मैं सेटटर को ओवरराइड कैसे करूं? सेटबाउंड ओवरराइडिंग खतरनाक प्रतीत होता है, अगर मैं सही ढंग से समझता हूं, तो गेटर और सेटर नाम सार्वजनिक इंटरफ़ेस का हिस्सा नहीं हैं और कभी भी बदल सकते हैं।मैं एक संपत्ति सेटर को कैसे ओवरराइड कर सकता हूं?

बेशक, मैं कक्षा में परिभाषित गुणों की सूची के लिए रनटाइम से पूछताछ करने के लिए class_copyPropertyList का उपयोग करता हूं, फिर इसे सेटटर के नाम के लिए पूछताछ करता हूं, और अंत में विधि जोड़ने के लिए class_addMethod का उपयोग करता हूं, पहले विधि के संदर्भ में पहले मूल संस्करण को कॉल करने के लिए उपयोग करने के लिए।

यह सब हैकी लगता है। क्या मैं चाहता हूं कि ऐसा करने का एक साफ तरीका है, जो भविष्य के ओएस संस्करणों को तोड़ने की गारंटी नहीं है? धन्यवाद।

+1

सीमाओं की संपत्ति UIView शीर्षलेख में परिभाषित की गई है, इसलिए आपकी टिप्पणी "गेटर और सेटर नाम सार्वजनिक इंटरफ़ेस का हिस्सा नहीं हैं और किसी भी समय बदल सकते हैं" सत्य नहीं है: '@property (nonatomic) CGRect सीमाएं' इसका मतलब है गेटर/सेटर 'सीमाएं '/' सेटबाउंड है: ' –

+0

हेडर में इंस्टेंस वैरिएबल घोषित भी हैं, लेकिन इसका मतलब यह नहीं है कि वे सार्वजनिक इंटरफ़ेस का हिस्सा हैं :) क्या यह कहना सही होगा कि http: // developer.apple.com/library/ios/#documentation/uikit/reference/UIView_Class/UIView/UIView.html सार्वजनिक इंटरफ़ेस है? इसमें सेटबाउंड का कोई उल्लेख नहीं है। –

उत्तर

19

आप (यानी ivars) वर्ग की आंतरिक स्थिति के आसपास प्रहार किए बिना एक सेटर/गेटर ओवरराइड कर सकते हैं - बस अपने ओवरराइड की सुपर के तरीकों कॉल:

- (Thing *)thing { 
    // do your extra stuff here 
    // ... 

    return [super thing]; 
} 

- (void)setThing:(Thing *)thing { 
    // do your extra stuff here 
    // ... 

    [super setThing:thing]; 
} 

एक वैकल्पिक कि सूट हो सकता है आपके समस्या KVO का उपयोग करना है।

अद्यतन

बेशक

, setBounds अधिभावी आवश्यक नहीं हो सकता है। this question देखें - layoutSubviews फ्रेम को बदलता है या सीमाओं को बदलने से फ्रेम आकार को भी अपडेट किया जा सकता है। तो अपने कोड को layoutSubviews में डालने पर विचार करें।

अंतिम अद्यतन

ठीक है, यहाँ क्यों एप्पल अचानक एक गैर मानक विधि के नाम (आपको डर लगता है के रूप में) का उपयोग कर के रूप में कुछ @property आइटम घोषित करने के लिए कभी नहीं जा रहा है है:

यह सब कुछ टूट जाएगा ऐप स्टोर

इस बारे में सोचें: संकलन समय पर, कोई भी कोड जो डॉट नोटेशन का उपयोग करके किसी संपत्ति का उपयोग करता है, उदा। obj.x सिंटैक्टिक चीनी, [obj x] के रूप में परिवर्तित किया गया है। इसी तरह गुणों के लिए - वे संकलन समय पर नियमित तरीकों में परिवर्तित हो जाते हैं। तो, संकलित बाइनरी डॉट नोटेशन और गुणों के बारे में कुछ नहीं जानते - वे केवल नियमित चयनकर्ताओं को कॉल करते हैं। तो यदि ऐप्पल ने आईओएस को एक अपडेट जारी किया जिसने कुछ सार्वजनिक गुणों को गैर मानक कार्यान्वयन विधियों के रूप में घोषित किया, तो ऐप स्टोर में सबकुछ टूट सकता था। सब कुछ। इस परिदृश्य में आपकी ओर से कोई गलती नहीं है यदि आपका ऐप बाकी की तरह टूट गया - यह ऐप्पल की गलती होगी, न कि आपके।

+0

यह मेरी चिंता का समाधान नहीं करता है - क्या होगा यदि सेटर नाम आईओएस 5 में सेटव्यूबाउंड में बदल जाता है? मुझे http://developer.apple.com/library/ios/#documentation/uikit/reference/UIView_Class/UIView/UIView.html पर UIView दस्तावेज़ों पर कहीं भी सेटबाउंड नाम नहीं मिला है, इसलिए मुझे विश्वास नहीं है कि मैं कर सकता हूं उस पर भरोसा। क्या मैं कुछ भूल रहा हूँ? –

+0

दूसरे शब्दों में, सेटर नाम वर्ग की आंतरिक स्थिति का हिस्सा है। –

+0

@ कार्तिक-वद्दाडी सेटर नाम संपत्ति 'सीमा' से लिया गया है जो प्रकाशित एपीआई का हिस्सा है और इसलिए किसी भी कारण से बदलने की संभावना बहुत कम है। सेटर नामों के लिए पैटर्न 'setX' है - यह बदलने वाला नहीं है, क्योंकि बिल्कुल सबकुछ हर जगह तोड़ देगा, सिर्फ आपका कोड नहीं! मुझे पूरा भरोसा है कि 'सेटबाउंड्स' और 'सीमाएं' विधियां कुछ और में बदलने वाली नहीं हैं। – occulus

2
@property(nonatomic) CGRect bounds; 

,

-(CGRect)bounds; 
-(void)setBounds:(CGRect)bounds; 

के लिए आशुलिपि है

view.bounds = rect; 

[view setBounds:rect]; 

के लिए आशुलिपि है,

CGRect rect = view.bounds; 

वाक्यात्मक चीनी हैं

CGRect rect = [view bounds]; 

डॉट संकेतन और @property घोषणाओं के लिए आशुलिपि है। वे कोड और सुविधा को छोटा करने के लिए हैं। संदेश और चयनकर्ता हमेशा उनके नीचे हमेशा रहते हैं, और इंटरफ़ेस का सबसे स्थिर, यदि स्थिर नहीं है, तो हमेशा स्थिर होने पर भरोसा किया जा सकता है।

"सेटबाउंड्स:" ओवरराइड करना यह करने का एक सुरक्षित तरीका है। "सेटबाउंड्स:" स्पष्ट रूप से सार्वजनिक इंटरफ़ेस में नामित नहीं है, क्योंकि इसे @property के रूप में घोषित किया गया है। हालांकि मानक यह है कि "सेट" के साथ सेटटर - कैपिटलकृत संपत्ति का नाम हमेशा बनाया जाता है (जब तक कि इसे पढ़ा न जाए)।

+0

कृपया ऊपर मेरी टिप्पणियां देखें। @property को एक अलग सेटर नाम का उपयोग करने के लिए बदला जा सकता है। –

+0

यूप, लेकिन ऐप्पल ऐसा नहीं करेगा, क्योंकि यह इतनी सारी चीज़ें तोड़ देगा। वे आंतरिक इवर वैरिएबल नाम (जो आपसे छिपा हुआ है) को बदलने की अधिक संभावना है, लेकिन सार्वजनिक संपत्ति का नाम अकेला छोड़ दें। – occulus

+0

@ कार्तिक-वद्दाडी यह इंटरफ़ेस घोषणा का हिस्सा है जो लाइब्रेरी के उपभोक्ताओं के साथ एक स्थापित अनुबंध है। किसी भी अन्य वस्तु या कार्य के रूप में उस पर भरोसा करना सुरक्षित है। आप पूरे ढांचे में हर एक विधि नाम के बारे में भी चिंता कर सकते हैं। –

0

ओएसएक्स में एक NSViewBoundsDidChange अधिसूचना है। यह बेहतर समाधान प्रतीत होता है, हालांकि @property विधियों को ओवरराइड करने का डर निराधार लगता है। मैं इस पोस्ट पर एक्सेसर्स को ओवरराइड करने के बारे में एक ही प्रश्न के साथ हुआ, और आपने मुझे अधिसूचनाओं को प्राथमिकता देने के लिए आश्वस्त किया है।

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