Подпись метода для селектора - PullRequest
2 голосов
/ 22 января 2010

Я новичок в бизнесе Objective C (большую часть времени занимаюсь Java-разработкой) и сейчас просыпаюсь с моим первым убийственным приложением. :-) На данный момент я как-то запутался в использовании селекторов в качестве аргументов метода. Например, они немного отличаются от делегатов в C #.

Учитывая следующую сигнатуру метода

-(void)execute:(SEL)callback;

существует ли способ принудительного применения подписи для селектора, передаваемого такому методу? Метод ожидает селектор метода со следующей сигнатурой

-(void)foo:(NSData*)data;

Но SEL (тип) является общим, поэтому есть хороший шанс передать неправильный селектор выполнить метод. Хорошо, по крайней мере, во время выполнения можно было бы увидеть забавное поведение ... но я хотел бы видеть предупреждение / ошибку компилятора, когда это происходит.

Ответы [ 3 ]

6 голосов
/ 22 января 2010

Быстрый ответ: нет, нет способа заставить компилятор принудительно использовать сигнатуру метода селектора метода, который предоставляется с помощью аргумента SEL.

Одной из сильных сторон Objective-C является то, что это язык со слабой типизацией, который допускает гораздо более динамичное поведение. Конечно, это происходит за счет безопасности типов во время компиляции.

Для того, чтобы делать то, что (я думаю) вы хотите, лучше всего использовать делегатов. Какао использует делегаты, чтобы позволить другому классу реализовать методы типа «обратного вызова». Вот как это может выглядеть:

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];
2 голосов
/ 22 января 2010

Чтобы прямо ответить на ваш вопрос, нет, тип SEL допускает любой тип селектора, а не только те, которые имеют определенную подпись.

Возможно, вы захотите передать объект вместо SEL и документ, подтверждающий, что переданный объект должен ответить на конкретное сообщение. Например:

- (void)execute:(id)object
{
    // Do the execute stuff, then...
    if ([object respondsToSelector:@selector(notifyOnExecute:)]) {
        [object notifyOnExecute:self];
    }
    // You could handle the "else" case here, if desired
}
0 голосов
/ 22 января 2010

Если вы хотите наладить обработку данных, используйте isKindOfClass внутри вашего селектора. Это очень похоже на экземпляр, с которым вы знакомы в Java.

...