19

IMP उद्देश्य-सी में टाइप करें, जहां तक ​​मैं समझता हूं, एक फ़ंक्शन पॉइंटर का प्रतिनिधित्व करता है। क्या ब्लॉक पॉइंटर से IMP बनाने का कोई तरीका है? आपके विचारों के लिए धन्यवाद।किसी उद्देश्य-सी ब्लॉक से एक आईएमपी बनाना

+1

मैंने टैग का एक गुच्छा जोड़ा; 'उद्देश्य-सी-रनटाइम' एक बहुत ही सामान्य रूप से इस्तेमाल किया जाने वाला टैग नहीं है और यह [बहुत ही रोचक] प्रश्न खरपतवार में बंद था। – bbum

+0

इसके लिए धन्यवाद, बीबीएम! –

+0

हालांकि, ब्लॉक से आईएमपी प्राप्त करने का लक्ष्य क्या है? – user102008

उत्तर

27

चूंकि यह लिखा गया था अब आईओएस और मैक ओएस एक्स में एपीआई है जो ब्लॉक को सीधे आईएमपी में बदलने की अनुमति देता है। मैंने एपीआई (imp_implementationWithBlock()) का वर्णन करते हुए weblog post लिखा है।


एक ब्लॉक प्रभावी रूप से एक संरचना है कि मेटाडाटा का एक सा होता है, ब्लॉक के भीतर निहित कोड के लिए एक संदर्भ और स्थिरांक-कॉपी किए गए डेटा ब्लॉक के भीतर कब्जा कर लिया की एक प्रति।

इस प्रकार, नहीं, IMP और ब्लॉक संदर्भ के बीच सीधे मानचित्र करने का कोई तरीका नहीं है।

जब किसी ब्लॉक को कॉल किया जाता है, तो संकलक एक ट्रैम्पोलिन उत्सर्जित करता है जो स्टैक फ्रेम सेट करता है और फिर ब्लॉक के भीतर निष्पादन योग्य कोड पर कूदता है।

हालांकि, आप क्या कर सकते हैं, एक आईएमपी बना है जो उस ट्रैम्पोलिन की तरह कार्य करता है। निम्नलिखित के लिए, आपको & रिटर्न प्रकारों के प्रत्येक सेट के लिए एक विशिष्ट आईएमपी की आवश्यकता होगी। यदि आपको यह सामान्य बनाना है, तो आपको असेंबली का उपयोग करने की आवश्यकता होगी।

इसके लिए, मैं कक्षा के प्रति उदाहरण अद्वितीय ब्लॉक उदाहरण स्थापित कर रहा हूं। यदि आप एक सामान्य ब्लॉक चाहते हैं जो सभी मामलों में कार्य करता है, तो SEL -> प्रति वर्ग ब्लॉक के हैश का निर्माण करें।

(1) संबद्ध संदर्भ तंत्र का उपयोग कर आईएमपी के रूप में कार्य करने के लिए सहयोगी ब्लॉक। कुछ की तरह:

void (^implementingBlock)(id s, SEL _c, int v) = ^(id s, SEL _c, int v) { 
    // do something here 
} 

objc_setAssociatedObject(obj, SELToImp, [implementingBlock copy])); 

(2) इस तरह की एक ट्रैम्पोलिन छोटा सा भूत कुछ को लागू:

void void_id_sel_intTramp(id self, SEL _cmd, int value) { 
    int (^block)(id s, SEL _c, int v) = objc_getAssociatedObject(self, _cmd); 
    block(self, _cmd, value); 
} 

(3) ऑब्जेक्टिव-सी क्रम के एपीआई के माध्यम से किसी भी चयनकर्ता के लिए में ऊपर ट्रैम्पोलिन सामान (method_setImplementation देख सकते हैं और की तरह)

चेतावनियां:

  • इस StackOverflow में टाइप किया गया था। वास्तविक कोड समान होगा, लेकिन संभावना थोड़ा अलग है।

  • [कार्यान्वयन ब्लॉक कॉपी] महत्वपूर्ण है; ब्लॉक ढेर (आमतौर पर)

+0

वास्तव में अच्छा समाधान, बहुत बहुत धन्यवाद! मैं इसे आज़माउंगा। मैं चयनकर्ताओं के खिलाफ मैप किए गए ब्लॉक के हैश का उपयोग करके समाप्त हुआ, लेकिन मैंने इसे 'एनएसएमयूटेबल डिक्शनरी' आवृत्ति चर में संग्रहीत किया। मैंने कभी भी 'objc_setAssociatedObject' का उपयोग करने का विचार नहीं किया, हालांकि। ये तो बहुत खूब है। –

+0

वैसे, क्या आपको लगता है कि आप पूरी असेंबली चीज पर विस्तार कर सकते हैं? मैं उस से मोहक हूं, लेकिन मैं वास्तव में बहुत अच्छी तरह से समझ नहीं पा रहा हूं कि यह सब कैसे काम करता है। –

+0

आईओएस 4.3 और मैक ओएस एक्स 10.7 में, imp_implementationWithBlock() है, [लेकिन मुझे लगता है कि आप पहले से ही जानते थे] (http://www.friday.com/bbum/2011/03/17/ios-4-3-imp_implementationwithblock /)। – lemnar

10

मेरा मानना ​​है कि माइक ऐश, लंदन फुलर से कुछ मदद के साथ, IOS सहित सामान्य मामले, है, जो कठिन है के लिए इस को हल किया है पर जीवन शुरू करते हैं। उनके पास github पर एक कक्षा है जो एक ब्लॉक को एक फ़ंक्शन पॉइंटर में बदल देगा।

आप announcement और कोको-अनबाउंड पर कुछ रोचक अनुवर्ती चर्चा भी देना चाहेंगे।

अद्यतन: और अब ऊपर उल्लिखित imp_implementationWithBlock() है।

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