6

मैं यह पता लगाने की कैसे चीजें वास्तव में काम करते हैं की कोशिश करो। तो मैंने सोचा कि जब मैं श्रेणियों का उपयोग करके कुछ तरीकों को ओवरराइट कर दूंगा, तो मुझे दिलचस्प एनएसएलॉग मिलेगा।किसी श्रेणी के साथ विधि को ओवरराइट करते समय मूल कार्यान्वयन को कैसे कॉल करें?

@implementation UIView(Learning) 
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 
    NSLog(@"-hitTest:withEvent: event=%@", event); 
    return [self hitTest:point withEvent:event]; 
} 
@end 

सुपर और स्वयं यहां काम नहीं करते हैं। क्या मूल कार्यान्वयन को कॉल करने का कोई तरीका है- hitTest: withEvent :? मैं जो चाहता हूं वह हर बार एक एनएसएलओजी है- हिटटेस्ट: के साथ: UIView पर कॉल किया जाता है।

यह सिर्फ व्यक्तिगत सीखने प्रयोजनों के लिए है। मैं कार्रवाई में घटना वितरण देखना चाहता हूँ।

+0

सुपर एक वर्ग में है क्योंकि आप 'काम नहीं करता है इसे एक ही कक्षा में नहीं बुलाओ, आप इसे कक्षा के सुपर पर बुला रहे हैं। तो इस मामले में, सुपर एक यूआईआरस्पॉन्डर है जिसमें हिटटेस्ट नहीं है: एवेन्ट विधि के साथ। स्वयं को कॉल करने से केवल एक अनंत लूप में परिणाम होता है क्योंकि आप हिटटेस्ट ओवरराइड कर रहे हैं: "स्वयं" के साथ Ivent। –

+0

मेरी टिप्पणी यहां जगह से थोड़ी दूर दिखती है, लेकिन पिछली टिप्पणी से पहले इसे समझ में आया था। –

उत्तर

14

तुम कर सकते हो, लेकिन एक वर्ग का उपयोग नहीं। एक श्रेणी एक विधि की जगह लेता है। (चेतावनी, कार समानता) यदि आपके पास कार है, और आप उस कार को नष्ट कर देते हैं और इसे एक नई कार से बदलते हैं, तो क्या आप अभी भी पुरानी कार का उपयोग कर सकते हैं? नहीं, क्योंकि यह चला गया है और अब अस्तित्व में नहीं है। श्रेणियों के साथ ही।

क्या तुम कर सकते हो रनटाइम पर एक अलग नाम से विधि जोड़ने के लिए (जैसे कि, "bogusHitTest:withEvent:") ऑब्जेक्टिव-सी क्रम का उपयोग करें, तो hitTest:withEvent: और bogusHitTest:withEvent: के कार्यान्वयन स्वैप है। इस तरह जब कोड कॉल hitTest:withEvent:, यह कोड है कि मूल रूप bogusHitTest:withEvent: लिए लिखा गया था निष्पादित करने के लिए जा रहा है। उसके बाद आप उस कोड को bogusHitTest:withEvent: का आह्वान कर सकते हैं, जो मूल कार्यान्वयन निष्पादित करेगा।

तो फर्जी विधि दिखाई देगा:

- (UIView *) bogusHitTest:(CGPoint)point withEvent:(UIEvent *)event { 
    NSLog(@"executing: %@", NSStringFromSelector(_cmd)); 
    return [self bogusHitTest:point withEvent:event]; 
} 

कोड तरीकों स्वैप करने के लिए की तर्ज पर कुछ होगा:

Method bogusHitTest = class_getInstanceMethod([UIView class], @selector(bogusHitTest:withEvent:)); 
Method hitTest = class_getInstanceMethod([UIView class], @selector(hitTest:withEvent:)); 
method_exchangeImplementations(bogusHitTest, hitTest); 
+0

ग्रेट। कम। काम करता है। धन्यवाद! –

0

दुर्भाग्य से, नहीं, कोई रास्ता नहीं एक विधि है कि आप को ओवरराइड के मूल कार्यान्वयन कॉल करने के लिए है। एक बार जब आप इसे श्रेणी में कार्यान्वित कर लेते हैं तो आपने मूल विधि को समाप्त कर दिया है।

अपने विधि में काम करना चाहिए super के लिए एक ही संदेश भेजा जा रहा; यह सुपरक्लास पर विधि सामान्य के रूप में कॉल करेगा (अगर कोई है)।

के रूप में मुझे यकीन है कि आप की खोज की है हूँ, self के लिए एक ही संदेश भेजा जा रहा अनंत लूप का निर्माण करेगा।

+1

जैसा कि एडम ने कहा है, इस तरह से यह संभव नहीं है, लेकिन आप विधि स्विजलिंग पर एक नज़र डाल सकते हैं। यहां एक शानदार उदाहरण है: http://github.com/marksands/UITextViewLinkOptions –

3

आप क्या करना चाहते क्या विधि swizzling कहा जाता है: http://www.cocoadev.com/index.pl?MethodSwizzling

+0

मुझे यकीन नहीं है, लेकिन लेख थोड़ा पुराना प्रतीत होता है। डेव डीलॉन्ग ने एक समाधान पोस्ट किया जो बहुत कम कोड के साथ काफी अच्छी तरह से काम करता है। धन्यवाद वैसे भी :-) –

+0

@ बुग अलर्ट बस इतना ही आपको पता है, मेरा कोड * है * विधि swizzling। लिंक्ड आलेख में इसके बारे में बहुत अधिक जानकारी है। :) –

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