2013-06-04 37 views
0

我使用的Objective-C的forwardInvocation:功能,我需要知道什麼說法類型收到的方法。在我的例子中,我通過了一個int,但是getArgumentTypeAtIndex:告訴我這是一個id。這裏有一個簡單的例子:預計參數類型是整數,但得到的ID,而不是

@interface Do : NSObject 
+ (void) stuff:(int)x; 
@end 
@implementation Do 
+ (NSMethodSignature *) methodSignatureForSelector:(SEL)selector 
{ 
    NSMethodSignature* signature = [super methodSignatureForSelector:selector]; 
    if (!signature) 
     signature = [self methodSignatureForSelector:@selector(forwardInvocation:)]; 
    return signature; 
} 

+ (void)forwardInvocation:(NSInvocation *)i 
{ 
    const char* argType = [i.methodSignature getArgumentTypeAtIndex:2]; 
    NSLog(@"%s == %s", argType, @encode(id)); // @ == @ 
    NSLog(@"%s == %s", argType, @encode(int)); // @ == i 
} 
@end 

以下是我把它叫做:

[Do stuff:123]; 

任何想法,爲什麼我沒有收到id代替int的類型?

回答

3

的問題是,你沒有真正對類stuff:方法,以便methodSignatureForSelector:將返回nil - 它看起來像你發現等來實現自己的版本,但失敗的super通話等結束返回forwardInvocation:的簽名 - 這不是你想要的!

要解決這個問題,您需要將methodSignatureForSelector:指向具有選擇器的類或使用協議 - 如果某個類實現了一個協議,那麼它將返回該協議中任何方法的簽名,即使方法實際上並未由該班級實施。

下面是一個使用協議的樣本:

@protocol DoProtocol 
@optional 
+ (void) stuff:(int)x; 
@end 

@interface Do : NSObject<DoProtocol> 
@end 

@implementation Do 

+ (void)forwardInvocation:(NSInvocation *)i 
{ 
    const char* argType = [i.methodSignature getArgumentTypeAtIndex:2]; 
    NSLog(@"%s == %s", argType, @encode(id)); // @ == @ 
    NSLog(@"%s == %s", argType, @encode(int)); // @ == i 
} 

@end 

@optional避免了未實現的方法的任何編譯器警告。 methodSignatureForSelector:(從NSObject)的默認實現將返回從協議獲得的有效簽名,因此將調用forwardInvocation:

+0

這是有效的,但在我的情況下,我需要添加一個類別的協議,而不是原始的'@ interface'聲明。無論出於何種原因,這似乎並不奏效。 – bendytree

+0

我最終直接從協議中提取簽名:'[NSMethodSignature signatureWithObjCTypes:protocol_getMethodDescription(@protocol(...),selector,0,0).types]' – bendytree

0

只要你能得到它過去的編譯器,不管你作爲參數傳遞將在運行時被解釋爲這樣的 - 你可以聲明一個函數接受一個NSNumber,但你傳遞一個UITableView給它,它的class仍然是UITableView

相關問題