@selector - с несколькими аргументами?
Я использую @selector
сегодня впервые и не смогли разобраться, как сделать следующее? Как бы вы написали @selector
если бы у вас было более одного аргумента?
Нет аргументов:
-(void)printText {
NSLog(@"Fish");
}
[self performSelector:@selector(printText) withObject:nil afterDelay:0.25];
Единственный аргумент:
-(void)printText:(NSString *)myText {
NSLog(@"Text = %@", myText);
}
[self performSelector:@selector(printText:) withObject:@"Cake" afterDelay:0.25];
Два аргумента:
-(void)printText:(NSString *)myText andMore:(NSString *)extraText {
NSLog(@"Text = %@ and %@", myText, extraText);
}
[self performSelector:@selector(printText:andMore:) withObject:@"Cake" withObject:@"Chips"];
Несколько аргументов: (т.е. более 2)
NSInvocation
8 ответов
- (id)performSelector:(SEL)aSelector
withObject:(id)anObject
withObject:(id)anotherObject
Из документации:
Этот метод аналогичен executeSelector: за исключением того, что вы можете указать два аргумента для aSelector. aSelector должен идентифицировать метод, который может принимать два аргумента типа id. Для методов с другими типами аргументов и возвращаемых значений используйте NSInvocation.
так что в вашем случае вы бы использовали:
[self performSelector:@selector(printText:andMore:)
withObject:@"Cake"
withObject:@"More Cake"]
В качестве альтернативы для NSInvocation, когда у вас более двух параметров, вы можете использовать NSObject 's -methodForSelector: как в следующем примере:
SEL a_selector = ...
Type1 obj1 = ...
Type2 obj2 = ...
Type3 obj3 = ...
typedef void (*MethodType)(id, SEL, Type1, Type2, Type3);
MethodType methodToCall;
methodToCall = (MethodType)[target methodForSelector:a_selector];
methodToCall(target, a_selector, obj1, obj_of_type2, obj_of_type3);
У меня была проблема, когда мне нужно было использовать afterDelay
наряду с несколькими аргументами в мой @selector
метод. Решение? Используйте функцию-обертку!
Скажи, что это функция, которую я хочу передать @selector
:
-(void)myFunct:(NSString *)arg1 andArg:(NSString *)arg2 andYetAnotherArg:(NSString *)arg3;
Очевидно, я даже не могу использовать withObject: withObject:
вот так, сделай обертку!
-(void)myFunctWrapper:(NSArray *)myArgs {
[self myFunct:[myArgs objectAtIndex:0] andArg:[myArgs objectAtIndex:1] andYetAnotherArg:[myArgs objectAtIndex:2]];
}
и используйте его, выполнив:
NSArray *argArray = [NSArray arrayWithObjects:string1,string2,string3,nil];
[self performSelector:@selector(myFunctWrapper:) withObject:argArray afterDelay:1.0];
Таким образом, я могу иметь несколько аргументов и использовать селектор с задержкой.
[self performSelector:@selector(printText:andMore) withObject:@"Cake" withObject:@"More Cake"];
Другой вариант - использовать еще более короткий синтаксис:
#import <objc/message.h> // objc_msgSend
...
((void (*)(id, SEL, Type1, Type2, Type3))objc_msgSend)(target, a_selector, obj1, obj_of_type2, obj_of_type3);
Разработка ответа Бен-Ури, который может быть написан короче.
Например, зовет UIView
метод - (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
можно сделать следующим образом:
SEL selector = @selector(covertPoint:toView:);
IMP method = [viewA methodForSelector:selector];
CGPoint pointInB = method(viewA, selector, pointInA, viewB);
Используя NSInvocation, как вы укажете, вы можете создать категорию NSObject, которая реализует
- (void)performSelector:(SEL)aSelector withObjects:(NSArray *)arguments;
Что-то вроде:
- (void)performSelector:(SEL)aSelector withObjects:(NSArray *)arguments
{
NSMethodSignature *signature = [self methodSignatureForSelector: aSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: signature];
[invocation setSelector: aSelector];
int index = 2; //
for (NSObject *argument in arguments) {
[invocation setArgument: &argument atIndex: index];
index ++;
}
[invocation invokeWithTarget: self];
}
из: iOS - Как реализовать executeSelector с несколькими аргументами и с afterDelay?
Как указал KennyTM, синтаксис селектора
@selector(printText:andMore:)
Вы называете это с
performSelector:withObject:withObject.
... если вам нужно больше аргументов или разных типов, вам нужно использовать NSIvocation