快速回答是:不,没有办法让编译器强制执行通过SEL
参数提供的方法选择器的方法签名。
Objective-C 的优势之一是它是弱类型语言,它允许更多的动态行为。当然,这是以编译时类型安全为代价的。
为了做你想做的(我认为),最好的方法是使用委托。Cocoa 使用委托来允许另一个类实现“回调”类型的方法。以下是它的外观:
FooController.h
@protocol FooControllerDelegate
@required:
- (void)handleData:(NSData *)data forFoo:(FooController *)foo;
@end
@interface FooController : NSObject
{
id <FooControllerDelegate> * delegate;
}
@property (assign) id <FooControllerDelegate> * delegate;
- (void)doStuff;
@end
FooController.m
@interface FooController (delegateCalls)
- (void)handleData:(NSData *)data;
@end
@implementation FooController
@synthesize delegate;
- (id)init
{
if ((self = [super init]) == nil) { return nil; }
delegate = nil;
...
return self;
}
- (void)doStuff
{
...
[self handleData:data];
}
- (void)handleData:(NSData *)data
{
if (delegate != nil)
{
[delegate handleData:data forFoo:self];
}
else
{
return;
// or throw an error
// or handle it yourself
}
}
@end
在您的委托协议中使用@required
关键字将阻止您将委托分配给FooController
未完全按照协议中描述的方法实现的方法。尝试提供与协议方法不匹配的委托@required
将导致编译器错误。
以下是您将如何创建一个委托类来使用上述代码:
@interface MyFooHandler <FooControllerDelegate> : NSObject
{
}
- (void)handleData:(NSData *)data forFoo:(FooController *)foo;
@end
@implementation MyFooHandler
- (void)handleData:(NSData *)data forFoo:(FooController *)foo
{
// do something here
}
@end
以下是您将如何使用所有内容:
FooController * foo = [[FooController alloc] init];
MyFooHandler * fooHandler = [[MyFooHandler alloc] init];
...
[foo setDelegate:fooHandler]; // this would cause a compiler error if fooHandler
// did not implement the protocol properly
...
[foo doStuff]; // this will call the delegate method on fooHandler
...
[fooHandler release];
[foo release];