2013-08-09 4 views
8

से मेल नहीं खाता है, मैं ब्लॉक-आधारित एपीआई के साथ काम कर रहा हूं और एक परिदृश्य में ठोकर खा रहा हूं जहां मैं एक ब्लॉक पैरामीटर में गुजर रहा था जिसमें हस्ताक्षर था जो typedef'd पैरामीटर से मेल नहीं खाता था विधि की उम्मीद थी। मेरे आश्चर्य के लिए, कंपाइलर इस पर ध्यान नहीं दे रहा था, और ऐप क्रैश नहीं हुआ था। क्या यह अपेक्षित व्यवहार है? उदाहरण:ब्लॉक पैरामीटर पास करना जो हस्ताक्षर

typedef void(^MyBlock)(); 
typedef void(^MyBlockWithParam)(id param); 

- (void)doWork { 
    MyBlockWithParam block1 = ^(id param) { 
     NSLog(@"block1: %@", param); 
    }; 

    MyBlock block2 = ^{ 
     NSLog(@"block2"); 
    }; 

    [self loadData:block1]; 
    [self loadData:block2]; 
} 

- (void)loadData:(MyBlockWithParam)block { 
    block(@"foo"); 
} 
+3

मुझे लगता है कि अगर आपने पहले को 'शून्य (^ MyBlockType) (शून्य) में बदल दिया है, तो आपको शिकायत मिल जाएगी। खाली '()' मतलब अनिर्दिष्ट तर्क मुझे विश्वास है। – nielsbot

+0

हाँ, जिसने संकलक को इसके बारे में शिकायत की है। क्या आप जानते हैं कि क्या कुछ दस्तावेज है (अगर वहां है तो मैंने इसे नहीं देखा)? अगर आप उत्तर के रूप में अपनी टिप्पणी पोस्ट करना चाहते हैं तो मैं इसे स्वीकार करूंगा। धन्यवाद – chinabuffet

+0

यकीन नहीं है - मुझे यह जानकारी किसी अन्य प्रश्न पर किसी अन्य उत्तर से मिली है :) मुझे देखने दो। – nielsbot

उत्तर

9

यह टाइप करने के लिए के रूप में में

typedef void(^MyBlock)(); 

का अर्थ है "अनिर्दिष्ट" तर्क एक खाली तर्क विनिर्देश प्रदान की जरूरत है । तो दो प्रकार लिखित के रूप में संगत हैं।

typedef void(^MyBlock)(void); 

निर्दिष्ट करता है कि ब्लॉक में कोई तर्क नहीं है और आपको कोई त्रुटि मिलेगी।

के & आर सी निर्दिष्ट करता है कि एक खाली तर्क सूची का अर्थ "अनिर्दिष्ट" है। सी ब्लॉक स्पेक का कहना है कि यह ब्लॉक प्रकार घोषणाओं के लिए सही नहीं है (सीएफ http://clang.llvm.org/docs/BlockLanguageSpec.html#block-variable-declarations) लेकिन: जीसीसी और क्लैंग दोनों के & आर व्यवहार को भाषा विस्तार के रूप में लागू करते हैं।

3

यह एक सी चीज है। एक खाली तर्क सूची के साथ एक फ़ंक्शन या ब्लॉक प्रोटोटाइप का अर्थ है "फ़ंक्शन (या ब्लॉक) आपको पसंद होने वाले किसी भी तर्क को लेता है"। आप संप्रेषित करने के लिए है कि ब्लॉक का कोई तर्क होना चाहिए चाहते हैं, आप स्पष्ट रूप से इस तरह तो कहने की जरूरत है:

typedef void(^MyBlock)(void) 

यह एएनएसआई से पहले के दिनों जब वहाँ समारोह प्रोटोटाइप और सभी समारोह घोषणाओं नहीं थे से बड़े पैमाने पर ऐतिहासिक है (बजना ब्लाकों विनिर्देश से

some_type function(); 
4

: परिभाषाओं के विपरीत) इस तरह देखा

variadic ... तर्क समर्थित हैं। [variadic.c] कोई ब्लॉक जो कोई तर्क नहीं लेता है उसे तर्क सूची [voidarg.c] में शून्य निर्दिष्ट करना होगा। एक खाली पैरामीटर सूची का प्रतिनिधित्व नहीं करता है, क्योंकि के & आर एक अनिर्दिष्ट तर्क सूची प्रदान करता है। नोट: दोनों gcc और clang समर्थन K & आर शैली सुविधा के रूप में।

असल में, यह सी सिंटैक्स का एक प्राचीन क्विर्क है। पुराने समय में, सी फ़ंक्शन घोषणा वाक्यविन्यास अलग था, और खाली कोष्ठक इंगित करते थे कि फ़ंक्शन किसी भी तर्क को पारित किया जा सकता है। पिछली संगतता के लिए, कंपेलरों ने आम तौर पर पुरानी शैली के फ़ंक्शन घोषणा वाक्यविन्यास की अनुमति दी है। और किसी कारण से, ऐप्पल ने ब्लॉक मानक में इस वाक्यविन्यास को एक साथ अस्वीकार करने का फैसला किया, जबकि वास्तव में इसे जीसीसी और क्लैंग दोनों में ब्लॉक के साथ उपयोग करने की इजाजत दी गई।

तो, लम्बी कहानी कम: घोषित करने के लिए है कि एक ब्लॉक का कोई तर्क लेता है, आप स्पष्ट रूप से के रूप में void(^MyBlock)(void)

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