2011-07-16 10 views
5

में तर्क प्रकार प्राप्त करना मैं एक निश्चित वर्ग को उपclass करने और अपने कुछ निजी तरीकों को ओवरराइड करने का प्रयास कर रहा हूं। यह खतरनाक है, असफल हो सकता है, ऐप्पल की समीक्षा (ऐपस्टोर में) को पार नहीं कर सका, भयानक प्रभाव हो सकता है, लेकिन यह सिर्फ प्रयोगात्मक/शैक्षणिक उद्देश्यों के लिए है :)एक विधि

उदाहरण के लिए मान लें कि मैं इस प्रकार को जानना चाहता हूं उदाहरण विधि UITextView की keyboardInput:shouldInsertText:isMarkedText: का पहला तर्क की:

SEL selector = @selector(keyboardInput:shouldInsertText:isMarkedText:); 
Class class = [UITextView class]; 
Method method = class_getInstanceMethod(class, selector); 
char *arg = method_copyArgumentType(method, 0); 
printf("_%s_\n", arg); 
free(arg); 

हालांकि कंसोल में मैं केवल [email protected]_ मिलता है। मुझे लगता है कि @ का अर्थ है ऑब्जेक्ट लेकिन किस वर्ग का ऑब्जेक्ट? (मैंने सोचा कि मुझे तर्क के वर्ग का नाम मिलेगा) क्या objective-c runtime functions या किसी अन्य माध्यम का उपयोग करके उस पैरामीटर की कक्षा प्राप्त करना संभव है?

पीएस: उदाहरण में मैंने कोको स्पर्श की एक कक्षा का उपयोग किया लेकिन मैं कोको के एक वर्ग के साथ बिल्कुल वही कोशिश कर सकता था। तो यह आईओएस के लिए विशिष्ट नहीं होना चाहिए।

हल:

मैं सिम्युलेटर क्या डेव सुझाव में की कोशिश की है, यह काम किया!

(gdb) info all-registers मुझे मूल्यों की एक लंबी सूची है, ...

((gdb) po *(id*)($ebp + 8) 
<MyTextView: 0x5911270; baseClass = UITextView; frame = (80 70; 240 323); text = 'Lorem ipsum dolor sit er ...'; clipsToBounds = YES; autoresize = RM+BM; layer = <CALayer: 0x5c0c7d0>; contentOffset: {0, 0}> 

(gdb) p *(SEL*)($ebp + 12) 
$5 = (SEL) 0xbd19 

(gdb) po *(id*)($ebp + 16) 
<UIWebDocumentView: 0xa02f000; frame = (0 0; 240 457); text = 'Lorem ipsum dolor sit er ...'; opaque = NO; userInteractionEnabled = NO; layer = <UIWebLayer: 0x5c35070>> 

(gdb) po *(id*)($ebp + 20) 
t 

(gdb) p *(id*)($ebp + 24) 
$6 = (id) 0x0 

कौन समझ में आता है के बाद से कुंजी मैं दबाया एक एकल "टी" था तो यह पाठ चिह्नित नहीं किया गया था ("0x0") तो मैं दे दी है यह सोचने के लिए ठीक है कि पहला तर्क UIWebDocumentView प्रकार होना चाहिए।

बस एक छोटी सी चीज (इस मामले में अप्रासंगिक), मैं जीबीडी में एसईएल से विधि का नाम कैसे प्राप्त कर सकता हूं? उदाहरण के लिए $5?

+0

'एसईएल' * * विधि का नाम है। सी स्ट्रिंग के रूप में चयनकर्ता प्राप्त करने के लिए 'sel_getName' फ़ंक्शन का उपयोग करें; http://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/ भी देखें। 'NSStringFromSelector' भी है, जो वास्तव में यह कहता है, और यह (और दस्तावेज में) फाउंडेशन का हिस्सा है। –

उत्तर

6

इस मान लिया जाये कि शैक्षिक हितों केवल ....

एक तरह से आप पता लगा सकता है GDB में प्रतीक पर तोड़ने के लिए और मानकों का निरीक्षण करने के लिए है। आप जानते हैं कि सामान्य तरह वे हैं (यानी, float बनाम object, आदि), ताकि आप उन्हें प्रिंट करने के लिए सही p कमांड का उपयोग कर सकें।

ब्रेकपाइंट सेट करने के लिए, आप या तो कर सकते हैं:

  1. gdb कंसोल में, प्रकार b -[UITextView keyboardInput:shouldInsertText:isMarkedText:]
  2. Xcode में, के लिए -[UITextView keyboardInput:shouldInsertText:isMarkedText:]

एक नया प्रतीकात्मक ब्रेकप्वाइंट जोड़ते हैं तो आप वास्तव में मारा ब्रेकपॉइंट, आप कुछ भी उपयोगी नहीं देख रहे हैं (बेशक)। लेकिन आप इस बिंदु पर तर्कों को प्रिंट कर सकते हैं, क्योंकि आप उनके आकार जानते हैं, और इस प्रकार उन्हें रजिस्टरों में होना चाहिए।

अधिक जानकारी के लिए कि वे किस रजिस्टरों में हैं, this handy blog post देखें। तुम भी सभी रजिस्टरों में सभी जानकारी बाहर मुद्रित करने के लिए, आदि info all-registers की तरह कुछ कर सकते हैं


अद्यतन

आप चयनकर्ता का नाम प्रिंट करना चाहते हैं, तो आप एक छोटे से उपयोग कर सकते हैं चाल है, जो कि चयनकर्ताओं * अधिक या कम कर रहे हैं char* रों:

p (char*)$5 

प्रिंट होगा:

${some number} = 0x{some address} "keyboardInput:shouldInsertText:isMarkedText:" 
+0

धन्यवाद, यह काम किया! मेरे पास एक आखिरी और थोड़ा संदेह है, हालांकि :) (कृपया अद्यतन उत्तर पढ़ें) – nacho4d

+0

@ nacho4d अद्यतन उत्तर –

+0

कमाल! महान जवाब :) – nacho4d

0

@ वास्तव में "ऑब्जेक्ट" का अर्थ है लेकिन आप यह नहीं समझ सकते कि यह किस वर्ग में है। यह बाइनरी के __OBJC सेगमेंट में सहेजा नहीं गया है और इस प्रकार आपके लिए तब तक उपलब्ध नहीं है जब तक आपके पास मूल हेडर फ़ाइल न हो।

आपको इसका अनुमान लगाना होगा। :)

9

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

+0

+1 क्योंकि यह मेरे उत्तर से अधिक सत्य है। –

+0

मैंने swizzling के बारे में सोचा, लेकिन इस मामले में अगर मुझे नहीं पता कि पहले तर्क के प्रकार swizzling कार्यान्वयन काम नहीं करेगा, मुझे विश्वास है। – nacho4d

+0

आप जानते हैं कि यह एक 'आईडी' है। आपको बस इतना ही चाहिए याद रखें, संकलन के बाद सभी 'id' बराबर बनाए जाते हैं। उस ने कहा, मुझे इस समस्या के लिए @ डेव डेलोंग के समाधान की तरह बेहतर लगता है। –

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