这看起来很简单,但我的大脑今天似乎没有工作,而且我的搜索没有得到有用的答案。
我有很多代码通过类别扩展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 :(得分:0)
我认为这是因为NSOutlineView
委托现在输入为id <NSOutlineViewDelegate>
而不是普通id
,就像在10.5 SDK中一样。该类别在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];
并且编译器应该没问题。由于该方法在协议中声明为可选方法,因此您仍希望在运行时检查委托是否实际响应选择器。