2012-11-22 22 views
7

Bu, başka bir şekilde söyleyebildiğim kadarıyla, SO üzerindeki "bir blok türünü kontrol edebilirmiyim" den farklıdır.Amaç-C tipi bir blok kontrol edin?

Bilinmeyen imzanın bir blok nesnesi verildiğinde, çağırmadan önce hangi argümanların kabul edildiğini öğrenebilir miyim?

Sözlüğümdeki nesnelerle ilişkili bir dizi geri dönüşüme sahip olduğum bir durum var. Bu geri bildirimlerin bazılarının farklı bir argüman seti beklemesini istiyorum. Buradaki örnek son derece basitleştirilmiştir, ancak bu noktaya dikkat çeker diye düşünüyorum.

Bir bloğun daha önce yazdığım bir türden olup olmadığını nasıl anlarım?

//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

ben cant düşünüyorum. Durumunuzda NSObject ek parametresini bırakıp kullanmazsanız sıfırlayabilirsiniz. – SAKrisT

+2

Bu örnekte, sözlük içindeki tüm bloklar için tutarlı bir imza kullanılması daha çok tercih edilir. Her blok içindeki kod, daha sonra hangi parametrelerin kullanılacağına veya yok sayılacağına bağımsız olarak karar verebilir. Ayrıca, bloğu arayabilmeniz için dönüş değerini "-objectForKey:" yerine blok imzanıza eklemelisiniz. Ayrıca, sözlüğe eklemeden önce her bloğu yığına kopyalamanız gerekir. – Darren

+0

Darren son iki ifadeniz hakkında ayrıntılı bilgi verebilir, teşekkür ederim! –

cevap

2

Açıkçası, geri aramaların farklı türleri varsa, farklı anahtarlar altında olmalıdırlar. Neden @"callbackWithOneParam" ve @"callbackWithTwoParams" anahtarlarını kullanmıyorsunuz? Bana göre, genel bir "geri arama" anahtarına ve geri dönüşü nasıl yorumlayacağınızı anlatmak için ayrı bir "tip" tuşa sahip olmaktan daha iyidir.

Fakat bunun gerçekten ne istediği, sözlükler yerine özel sınıfların nesnelerini kullanmaktır. Jenerik nesnelerin uygun olmayı bıraktığı sınırları çözdünüz ve çözdüklerinden daha fazla sorun oluşturmaya başlıyorsunuz.

+0

+1 kullanmalısınız. – BergQuester

-1

Sadece adın "Foo" veya "Bar" olup olmadığını kontrol edin. Muhtemelen sınıfın bazı biçimde onu sahip ve bir blok onun argümanları türünü bilmek GEREKİR ararken

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

gerçekten de 'isKindOfClass:' veya 'isMemberClass:' işlevini, bu amaçla bir sözlük üzerinde özel bir sınıf önermek için –

0

gitmeden ben mümkün isnt bir his var fonksiyonları parametreleri, kontrol kadar çok çaba olacaktır. Durumunuzda, "ad" argümanlarının ne olması gerektiğini belirlemek için yeterli değilse, bana söyleyecek olan başka bir anahtar "türü" ekleyeceğim. Eğer aksi muhtemelen programın çökmesine olacak doğru türe blok döküm zorunlu ki o

// 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"]; 

     } 
    } 
} 

Not: İşte bir örnek. Çünkü blok, derleyicinin argümanları doğru sıraya koyması ve herhangi bir dönüş türüne izin vermesidir.

0

Şahsen, ustaca CTBlockDescription ...

CTBlockDescription Eğer argümanları içeren blokları incelemek ve zamanında zaman özelliklerini derlemek sağlar kullanın.

[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} 

Muhteşem


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

...

İlgili konular