Аргументы в @selector - PullRequest
       37

Аргументы в @selector

35 голосов
/ 29 августа 2009

Есть ли способ передать аргументы в селекторе?

пример: У меня есть этот метод

- (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{

}

и мне нужно вызывать эту функцию через селектор, передавая два аргумента.

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(/*my method*/) userInfo:nil repeats:YES];

Как я могу это сделать?

Ответы [ 5 ]

56 голосов
/ 29 августа 2009

Вы можете использовать метод NSTimer:

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
                                 invocation:(NSInvocation *)invocation
                                    repeats:(BOOL)repeats;

Вместо этого, поскольку объект NSInvocation позволит вам передавать аргументы; NSInvocation объект, как определяют документы :

сообщение Objective C, представленное статическим, то есть это действие, превращенное в объект.

При создании объекта NSTimer с использованием селектора требуется формат метода:

- (void)timerFireMethod:(NSTimer*)theTimer

NSInvocation позволяет вам установить цель, селектор и аргументы, которые вы передаете:

SEL selector = @selector(myMethod:setValue2:);

NSMethodSignature *signature = [MyObject instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:selector];

NSString *str1 = @"someString";
NSString *str2 = @"someOtherString";

//The invocation object must retain its arguments
[str1 retain];
[str2 retain];

//Set the arguments
[invocation setTarget:targetInstance];
[invocation setArgument:&str1 atIndex:2];
[invocation setArgument:&str2 atIndex:3];

[NSTimer scheduledTimerWithTimeInterval:0.1 invocation:invocation repeats:YES];

Где MyObject - это класс, для которого myMethod:setValue2: объявлен и реализован - instanceMethodSignatureForSelector: - это вспомогательная функция, объявленная в NSObject, которая возвращает вам NSMethodSignature объект для передачи в NSInvocation.

Кроме того, отметим, что при setArgument:atIndex: индексы для аргументов, передаваемых методу, установленному в качестве селектора, начинаются с индекса 2. Из документов:

Индексы 0 и 1 указывают скрытые аргументы self и _cmd соответственно; Вы должны установить эти значения непосредственно с помощью методов setTarget: и setSelector :. Используйте индексы 2 и выше для аргументов, обычно передаваемых в сообщении.

27 голосов
/ 29 августа 2009

Для scheduledTimerWithTimeInterval: передаваемый селектор может иметь только один аргумент. Кроме того, его единственный аргумент должен быть NSTimer * объектом. Другими словами, селектор должен принимать следующую форму:

- (void)timerFireMethod:(NSTimer*)theTimer

Что вы можете сделать, это сохранить аргументы в словаре userInfo и вызвать нужный селектор из обратного вызова таймера:

- (void)startMyTimer {
    /* ... Some stuff ... */
    [NSTimer scheduledTimerWithTimeInterval:0.1 
                                     target:self 
                                   selector:@selector(callMyMethod:) 
                                   userInfo:[NSDictionary dictionaryWithObjectsAndKeys:someValue, 
                       @"value1", someOtherValue, @"value2", nil] 
                                    repeats:YES];
}

- (void)callMyMethod:(NSTimer *)theTimer {
    NSString *value1 = [[theTimer userInfo] objectForKey:@"value1"];
    NSString *value2 = [[theTimer userInfo] objectForKey:@"value2"];
    [self myMethod:value1 setValue2:value2];
}
2 голосов
/ 29 августа 2009

Похоже на работу для блоков (при условии, что она предназначена для Snow Leopard.)

-jcr

0 голосов
/ 19 июля 2013
Блоки

кажутся теперь очевидным ответом ... но есть еще одна идиома, которая была очень распространена в классической среде выполнения, объединяйте ваши аргументы в одном объекте:

 - (void)doMyMethod:(NSDictionary *)userInfo
 {
     [self myMethod: [userInfo objectForKey:@"value1"] setValue2: [userInfo objectForKey:@"value2"]];
 }
 - (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{

}

Теперь вы можете отправить на

[self performSelector:@selector(doMyMethod:) withObject:@{@"value1":@"value1",@"value2":@"value2"}];
0 голосов
/ 29 августа 2009
@selector(myMethod:setValue2:)

Поскольку селектор для вашего метода не просто называется myMethod, а вместо этого myMethod:setValue2:.

Также (и я мог бы быть неосновным здесь), я считаю, что технически вы можете опустить слова между двоеточиями и, таким образом, также использовать @selector(myMethod::), но не цитируйте меня по этому поводу, если другие не могут подтвердить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...