Создание селектора из имени метода с параметрами - PullRequest
57 голосов
/ 18 ноября 2008

У меня есть пример кода, который получает SEL от текущего объекта,

SEL callback = @selector(mymethod:parameter2);

И у меня есть метод, подобный

 -(void)mymethod:(id)v1 parameter2;(NSString*)v2 {
}

Теперь мне нужно переместить mymethod к другому объекту, скажем myDelegate.

Я пытался:

SEL callback = @selector(myDelegate, mymethod:parameter2);

но он не скомпилируется.

Ответы [ 3 ]

100 голосов
/ 18 ноября 2008

SEL - это тип, представляющий селектор в Objective-C. Ключевое слово @selector () возвращает описанный вами SEL. Это не указатель на функцию, и вы не можете передавать ему какие-либо объекты или ссылки любого рода. Для каждой переменной в селекторе (методе) вы должны представить это в вызове @selector. Например:

-(void)methodWithNoParameters;
SEL noParameterSelector = @selector(methodWithNoParameters);

-(void)methodWithOneParameter:(id)parameter;
SEL oneParameterSelector = @selector(methodWithOneParameter:); // notice the colon here

-(void)methodWIthTwoParameters:(id)parameterOne and:(id)parameterTwo;
SEL twoParameterSelector = @selector(methodWithTwoParameters:and:); // notice the parameter names are omitted

Селекторы обычно передаются методам делегирования и обратным вызовам, чтобы указать, какой метод следует вызывать для определенного объекта во время обратного вызова. Например, когда вы создаете таймер, метод обратного вызова специально определяется как:

-(void)someMethod:(NSTimer*)timer;

Поэтому, когда вы планируете таймер, вы должны использовать @selector, чтобы указать, какой метод на вашем объекте будет фактически отвечать за обратный вызов:

@implementation MyObject

-(void)myTimerCallback:(NSTimer*)timer
{
    // do some computations
    if( timerShouldEnd ) {
      [timer invalidate];
    }
}

@end

// ...

int main(int argc, const char **argv)
{
    // do setup stuff
    MyObject* obj = [[MyObject alloc] init];
    SEL mySelector = @selector(myTimerCallback:);
    [NSTimer scheduledTimerWithTimeInterval:30.0 target:obj selector:mySelector userInfo:nil repeats:YES];
    // do some tear-down
    return 0;
}

В этом случае вы указываете, что объект obj будет обмениваться сообщениями с myTimerCallback каждые 30 секунд.

18 голосов
/ 18 ноября 2008

Нельзя передать параметр в @selector ().

Похоже, вы пытаетесь реализовать обратный вызов. Лучший способ сделать это было бы примерно так:

[object setCallbackObject:self withSelector:@selector(myMethod:)];

Затем в setCallbackObject: withSelector: метод вашего объекта вы можете вызвать метод обратного вызова.

-(void)setCallbackObject:(id)anObject withSelector:(SEL)selector {
    [anObject performSelector:selector];
}
5 голосов
/ 18 ноября 2008

Помимо того, что уже было сказано о селекторах, вы можете взглянуть на класс NSInvocation.

NSInvocation - это сообщение Objective C, отображаемое как статическое, то есть это действие, превращенное в объект. Объекты NSInvocation используются для хранения и пересылки сообщений между объектами и между приложениями, главным образом объектами NSTimer и системой распределенных объектов.

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

Имейте в виду, что, хотя это полезно в определенных ситуациях, вы не используете NSInvocation в обычный день кодирования. Если вы просто пытаетесь заставить два объекта общаться друг с другом, рассмотрите возможность определения неформального или формального протокола делегата или передачи селектора и целевого объекта, как уже упоминалось.

...