Подтвердить что ты не робот

@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

4b9b3361

Ответ 1

 - (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"]

Ответ 2

В качестве альтернативы для NSInvocation, когда у вас есть более двух параметров, вы можете использовать NSObject - 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);

Ответ 3

У меня возникла проблема, когда мне нужно было использовать 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];

Таким образом, я могу иметь несколько аргументов и использовать селектор с задержкой.

Ответ 4

@selector(printText:andMore:)

Ответ 5

[self performSelector:@selector(printText:andMore) withObject:@"Cake" withObject:@"More Cake"];

Ответ 6

Другой вариант - использовать еще более короткий синтаксис:

#import <objc/message.h> // objc_msgSend
...
((void (*)(id, SEL, Type1, Type2, Type3))objc_msgSend)(target, a_selector, obj1, obj_of_type2, obj_of_type3);

Ответ 7

Разрабатывая ответ Бен-Ури, который может быть написан короче.

например. вызов метода 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);

Ответ 8

Как отметил KennyTM, синтаксис селектора

@selector(printText:andMore:)

Вы вызываете его с помощью

performSelector:withObject:withObject. 

... если вам нужно больше аргументов или разных типов, вам нужно использовать NSIvocation

Ответ 9

Используя 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?