2012-11-22 24 views
7

यह एसओ पर पोस्ट "ब्लॉक के प्रकार की जांच कर सकता है" पोस्ट से अलग है, जहां तक ​​मैं वैसे भी बता सकता हूं।उद्देश्य-सी प्रकार एक ब्लॉक की जांच करें?

मैं जानना चाहता हूं कि अज्ञात हस्ताक्षर के ब्लॉक ऑब्जेक्ट को देखते हुए, मैं यह जान सकता हूं कि यह किस तर्क को आमंत्रित करने से पहले स्वीकार करता है?

मेरे पास ऐसी स्थिति है जहां मेरे पास शब्दकोश में ऑब्जेक्ट्स से जुड़े कई कॉलबैक हैं। मैं उन कॉलबैक में से कुछ को तर्कों के एक अलग सेट की अपेक्षा करना चाहता हूं। यहां का उदाहरण बेहद सरल है, लेकिन मुझे लगता है कि यह बिंदु पूरी हो जाता है।

मैं कैसे पता लगा सकता हूं कि एक ब्लॉक एक प्रकार का है जिसे मैंने पहले टाइप किया था?

//MyClass.m 

// I start by declare two block types 
typedef void (^callbackWithOneParam)(NSString*); 
typedef void (^callbackWithTwoParams)(NSString*, NSObject*); 

........ 

// I create a dictionary mapping objects to callback blocks 

self.dict = @{ 
    @"name": "Foo", 
    @"callback": ^(NSString *aString) { 
    // do stuff with string 
    } 
}, { 
    @"name": "Bar", 
    @"callback": ^(NSString *aString, NSObject *anObject) { 
    // do stuff with string AND object 
    } 
} 

..... 

// Later, this method is called. 
// It looks up the "name" parameter in our dictionary, 
// and invokes the associated callback accordingly. 

-(void) invokeCallbackForName:(NSString*)name { 
    // What is the type of the result of this expression? 
    [self.dict objectForKey: name] 

    // I want to say: (pseudocode) 
    thecallback = [self.dict objectForKey: name]; 
    if (thecallback is of type "callbackWithOneParam") { 
     thecallback(@"some param") 
    } 
    else if (thecallback is of type "callbackWithTwoParams") { 
     thecallback(@"some param", [[NSObject alloc] init]); 
    } 
} 
+0

मैं आप नहीं कर सकते लगता है। आपकी स्थिति में आप अतिरिक्त पैरामीटर NSObject छोड़ सकते हैं और यदि आप इसका उपयोग नहीं करते हैं तो शून्य डाल दें। – SAKrisT

+2

इस उदाहरण में शब्दकोश के भीतर सभी ब्लॉक के लिए एक निरंतर हस्ताक्षर का उपयोग करना अधिक बेहतर है। प्रत्येक ब्लॉक के भीतर कोड स्वतंत्र रूप से तय कर सकता है कि कौन से पैरामीटर का उपयोग किया जाएगा या अनदेखा किया जाएगा। ब्लॉक को कॉल करने से पहले आपको अपने ब्लॉक हस्ताक्षर में '-objectForKey:' से वापसी मूल्य भी डालना होगा। आपको प्रत्येक ब्लॉक को शब्दकोश में जोड़ने से पहले ढेर में भी कॉपी करना होगा। – Darren

+0

डैरेन क्या आप अपने पिछले दो बयानों के बारे में विस्तार से बता सकते हैं, धन्यवाद! –

उत्तर

2

स्पष्ट रूप से, यदि कॉलबैक के अलग-अलग प्रकार हैं, तो वे अलग-अलग चाबियों के नीचे होना चाहिए। @"callbackWithOneParam" और @"callbackWithTwoParams" कुंजी का उपयोग क्यों न करें? मेरे लिए, कॉलबैक की व्याख्या करने के तरीके के बारे में बताने के लिए एक सामान्य "कॉलबैक" कुंजी और एक अलग "प्रकार" कुंजी होने से बेहतर है।

लेकिन यह वास्तव में क्या कहता है शब्दकोशों के बजाय कस्टम कक्षाओं की वस्तुओं का उपयोग करना है। आपने सीमा पार कर ली है जहां जेनेरिक ऑब्जेक्ट्स सुविधाजनक होने से रोकते हैं और हल करने से अधिक समस्याएं पैदा करते हैं।

+0

+1 शब्दकोश पर एक कस्टम क्लास की सिफारिश करने के लिए। – BergQuester

-1

बस यह जांचें कि नाम "फू" या "बार" है या नहीं? शायद सिर्फ वर्ग के किसी रूप में यह होने और

if ([myObject class] == [MyClass class]) 
+0

आपको वास्तव में 'isKindOfClass:' या 'isMemberClass:' का उपयोग करना चाहिए, इस उद्देश्य के लिए –

0

जा रहा जब बुला एक ब्लॉक आप अपने तर्कों का प्रकार पता होना चाहिए के बिना काम करता है मानकों, जो मैं संभव नहीं है एक लग रहा है की जाँच के रूप में के रूप में ज्यादा प्रयास होगा। आपके मामले में, यदि "नाम" पर्याप्त निर्धारित करने के लिए पर्याप्त नहीं है कि तर्क क्या होना चाहिए, तो मैं एक और कुंजी "प्रकार" जोड़ूंगा जो मुझे बताएगा।

// Callback dictionary 

_callbacks = @{ 
    @{@"name":@"foo", @"type":@(1), @"callback":^(int i) { NSLog(@"%d", i); }}, 
    @{@"name":@"bar", @"type":@(2), @"callback":^(int i, int j) { NSLog(@"%d", i+j); }}, 
    @{@"name":@"zap", @"type":@(3), @"callback":^(int i, int j, int k) { NSLog(@"%d", i+j+k); }}, 
    @{@"name":@"cab", @"type":@(4), @"callback":^(NSString *s) { NSLog(@"%lu",s.length); }}, 
    @{@"name":@"fog", @"type":@(5), @"callback":^(void) { NSLog(@"I can't see"); }} 
} 


-(void) invokeCallbackForName:(NSString*)name withArguments:(NSArray*)args { 

    NSDictionary *info = _callbacks[name]; 

    if (info != nil) { 
     id block = info[@"callback"]; 
     int type = [info[@"type"] intValue]; 
     switch (type) { 

      case 1: { 
       int arg1 = [args[0] intValue]; 
       ((void(^)(int)) block)(arg1); 
       break; 
      } 
      case 2: { 
       int arg1 = [args[0] intValue]; 
       int arg2 = [args[1] intValue]; 
       ((void(^)(int,int)) block)(arg1,arg2); 
       break; 
      } 
      case 3: { 
       int arg1 = [args[0] intValue]; 
       int arg2 = [args[1] intValue]; 
       int arg3 = [args[2] intValue]; 
       ((void(^)(int,int,int)) block)(arg1,arg2,arg3); 
       break; 
      } 
      case 5: { 
       NSString *arg1 = [args[0] intValue]; 
       ((void(^)(NSString*)) block)(arg1); 
       break; 
      } 
      default: 
       [NSExceptien raise:NSInvalidArgumentException format:@"Unsupported callback type"]; 

     } 
    } 
} 

नोट यह जरूरी है कि यह है कि आप को सही प्रकार पर ब्लॉक डाली अन्यथा आप शायद अपने कार्यक्रम दुर्घटना होगा: यहाँ एक उदाहरण है। ऐसा इसलिए है क्योंकि ब्लॉक सही क्रम में स्टैक पर तर्क डालने और किसी भी वापसी प्रकार की अनुमति देने के लिए कंपाइलर पर निर्भर करता है।

0

व्यक्तिगत रूप से, मैं सरल CTBlockDescription ...

CTBlockDescription आप तर्क सहित ब्लॉक का निरीक्षण किया और रनटाइम पर समय सुविधाओं संकलन सुविधा देता है।

BOOL(^bk)(BOOL,id) = ^BOOL(BOOL ani, id obj) { return YES; }; 

[CTBlockDescription.alloc initWithBlock:bk].blockSignature.description; 

<NSMethodSignature: 0x253f080> 
    number of arguments = 3 
    frame size = 12 
    is special struct return? NO 
    return value: -------- -------- -------- -------- 
     type encoding (c) 'c' 
     flags {isSigned} 
     modifiers {} 
     frame {offset = 0, offset adjust = 0, size = 4, size adjust = -3} 
     memory {offset = 0, size = 1} 
    argument 0: -------- -------- -------- -------- 
     type encoding (@) '@?' 
     flags {isObject, isBlock} 
     modifiers {} 
     frame {offset = 0, offset adjust = 0, size = 4, size adjust = 0} 
     memory {offset = 0, size = 4} 
    argument 1: -------- -------- -------- -------- 
     type encoding (c) 'c' 
     flags {isSigned} 
     modifiers {} 
     frame {offset = 4, offset adjust = 0, size = 4, size adjust = -3} 
     memory {offset = 0, size = 1} 
    argument 2: -------- -------- -------- -------- 
     type encoding (@) '@' 
     flags {isObject} 
     modifiers {} 
     frame {offset = 8, offset adjust = 0, size = 4, size adjust = 0} 
     memory {offset = 0, size = 4} 

गॉर्जियस ...