SEL
簡単な答えは次のとおりです。いいえ、引数を介して提供されるメソッドセレクターのメソッドシグネチャーをコンパイラーに強制させる方法はありません。
Objective-C の強みの 1 つは、より動的な動作を可能にする弱い型付けの言語であることです。もちろん、これにはコンパイル時の型の安全性が犠牲になります。
(私が思うに) やりたいことを行うには、デリゲートを使用するのが最善の方法です。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];