2011-06-03 28 views
0

這似乎是一件簡單的事情,但我的大腦今天似乎沒有工作,我的搜索沒有找到有用的答案。如何在類別中擴展Cocoa協議以避免「在協議中找不到」警告?

我有很多通過類別擴展可可類的代碼(它也是open source)。有些方法想要調用委託;舊的代碼中使用的非正式協議,要做到這一點,但現在建設目標10.6的時候,我得到警告:

warning: '-outlineView:menuForTableColumn:byItem:' not found in protocol(s) 

舉個例子,這裏有一個類別:

@interface NSOutlineView (DSOutlineViewCategories) 

- (NSMenu *)menuForEvent:(NSEvent *)event; 

@end 

其中使用的非正式協議聲明一個委託方法:

@interface NSObject (DSTableViewDelegate) 

- (NSMenu *)outlineView:(NSOutlineView *)olv menuForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; 

@end 

和實現調用的委託:

@implementation NSOutlineView (DSOutlineViewCategories) 

- (NSMenu *)menuForEvent:(NSEvent *)event 
{ 
    NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil]; 
    NSInteger column = [self columnAtPoint:point]; 
    NSInteger row = [self rowAtPoint:point]; 
    id item = [self itemAtRow:row]; 

    if (column >= 0 && item && [[self delegate] respondsToSelector:@selector(outlineView:menuForTableColumn:byItem:)]) 
     return [[self delegate] outlineView:self menuForTableColumn:[[self tableColumns] objectAtIndex:column] byItem:item]; 
    else 
     return [super menuForEvent:event]; 
} 

@end 

我該如何更新此代碼10.6(及更高版本),以避免「在協議中找不到」警告?

回答

0

我認爲這是因爲NSOutlineView代表現在被輸入爲id <NSOutlineViewDelegate>而不是像原來在10.5 SDK中的普通id。該類別在NSObject上聲明,但是編譯器沒有看到代理對象從NSObject繼承,所以它不能識別它會響應該消息。之前,由於代表是一個普通的id,它不會抱怨發送給它的任何消息,只要它可以在某處找到聲明即可。

的快速和骯髒的解決將是隻需添加一個演員,使代碼[(id)[self delegate] outlineView:self menuForTableColumn:[[self tableColumns] objectAtIndex:column] byItem:item];

是一個小更正式,你可以宣佈自己正式的委託協議,由NSOutlineViewDelegate繼承,這看起來像

@protocol DSOutlineViewDelegate <NSOutlineViewDelegate> 

@optional 
- (NSMenu *)outlineView:(NSOutlineView *)olv menuForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; 

@end 

然後,在調用它的代碼中,您將希望在類型爲id <DSOutlineViewDelegate>的對象上調用該方法。您可以通過聲明與鑄塑件對你來說,就像一個新的方法做到這一點:

- (id <DSOutlineViewDelegate>)ds_delegate 
{ 
    return (id <DSOutlineViewDelegate>)[self delegate]; 
} 

然後,在實際的代碼,你會打電話:

[[self ds_delegate] outlineView:self menuForTableColumn:[[self tableColumns] objectAtIndex:column] byItem:item]; 

和編譯器應該OK接着就,隨即。由於該方法在協議中聲明爲可選,您仍然希望在運行時檢查委託是否實際響應選擇器。

+0

非常感謝。這確實解決了它。我曾考慮過創建一個這樣的協議,但是避開了使用演員陣容;通常是一面紅旗。但在這種情況下完全合適。 – Dejal 2011-06-04 05:05:29