@selector - с несколькими аргументами? - PullRequest
26 голосов
/ 19 февраля 2010

Сегодня я впервые пользуюсь @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

Ответы [ 9 ]

36 голосов
/ 19 февраля 2010

 - (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"]
17 голосов
/ 10 августа 2012

В качестве альтернативы для NSInvocation, когда у вас есть более двух параметров, вы можете использовать -methodForSelector NSObject: как в следующем примере:

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);
14 голосов
/ 24 мая 2011

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

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

5 голосов
/ 19 февраля 2010
@selector(printText:andMore:)
4 голосов
/ 30 сентября 2012

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

#import <objc/message.h> // objc_msgSend
...
((void (*)(id, SEL, Type1, Type2, Type3))objc_msgSend)(target, a_selector, obj1, obj_of_type2, obj_of_type3);
4 голосов
/ 19 февраля 2010
[self performSelector:@selector(printText:andMore) withObject:@"Cake" withObject:@"More Cake"];
2 голосов
/ 29 августа 2012

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

Например, вызов метода 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);
1 голос
/ 19 февраля 2010

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

@selector(printText:andMore:)

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

performSelector:withObject:withObject. 

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

0 голосов
/ 02 мая 2019

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

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