我在课堂上有这个
[delegate performSelector:@selector(doStuff:) withObject:myObject afterDelay:2.0];
我有这个错误
警告: '-performSelector:withObject:afterDelay:' 在协议中找不到
我无法弄清楚可能出现的问题。
任何线索?
感谢。
答案 0 :(得分:30)
您的问题是您已将委托实例变量声明为:
id<SomeProtocol> delegate;
右?嗯,这意味着编译时检查器只会在<SomeProtocol>
协议中查找方法。但是,performSelector:withObject:afterDelay:
上已声明NSObject
。这意味着您应该将ivar声明为:
NSObject<SomeProtocol> * delegate;
这表示它必须是符合NSObject
的{{1}},而不是符合<SomeProtocol>
的任何对象。这应该摆脱你的警告,你不必做任何演员。
答案 1 :(得分:3)
首先尝试将委托转换为其类'type,然后调用performSelector:withObject:afterDelay
:
[(SomeClass *) delegate performSelector:@selector(doStuff:) withObject:myObject afterDelay:2.0];
假设您的delegate
类型为id
,您需要告诉运行时该对象实际上确实从NSObject
继承(其中performSelector:withObject:afterDelay:
方法已定义通过将其转换为类的类型。
答案 2 :(得分:3)
尽管Dave提出的NSObject *
演员会工作,但是有一种更清晰的替代方式可以让人们按照他们的预期使用协议 - 你可以让协议本身声明它支持NSObject协议。
NSObject不仅是一个实现,还是一个包含所有performSelector:方法变体的协议。因此,您可以在协议中声明您支持NSObject,就像您支持协议的任何其他类一样:
@protocol MyProtocol <NSObject>
编译器警告将消失(假设您已导入协议定义)。
请注意,这确实意味着前进任何声明支持您的协议的人几乎必须是NSObject或继承许多方法。但是,由于实际考虑,iPhone编程中使用的所有类都来自NSObject,所以这通常不是问题。
编辑:
事实证明-performSelector:withObject:afterDelay:
不在NSObject协议中(没有延迟的协议)。因为对于每个使用你的协议的人来说,如果他们只能使用id引用协议类型,它仍然会更好,我仍然会使用协议来解决这个问题 - 但是你必须自己声明NSObject协议的扩展。因此,在文件的标题中,您可以添加以下内容:
@protocol MyProtocolNSObjectExtras <NSObject>
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
@end
@protocol MyProtocol <NSObjectExtras>
....
@end
然后你获得了我之前描述的所有相同的好处。
答案 3 :(得分:2)
您需要将委托对象强制转换为您正在使用的实际类,以便拥有这些方法。看到委托只能显示协议中定义的方法。 performSelector:withObject:不是协议中定义的方法。
[(CLASS*)delegate performSelector:@selector(doStuff:) withObject:myObject afterDelay:2.0];
答案 4 :(得分:1)
[NSTimer scheduledTimerWithTimeInterval:2
target:self
selector:@selector(doStuff)
userInfo:nil
repeats:NO];
尝试假设您只想要一个计时器