2010-02-19 8 views
25

Я использовал @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

+0

Обновлено отражает ответы, спасибо за всю помощь, высоко ценится. – fuzzygoat

+1

ваши «двойные аргументы» не имеют задержки – user102008

ответ

35

 

- (id)performSelector:(SEL)aSelector 
      withObject:(id)anObject 
      withObject:(id)anotherObject 

От Documentation:

Этот метод так же, как performSelector: за исключением того, что вы можете поставить два аргумента для aSelector. aSelector должен идентифицировать метод, который может принимать два аргумента типа id. Для методов с другими типами аргументов и возвращаемыми значениями используйте NSInvocation.

так в вашем случае, вы будете использовать:

[self performSelector:@selector(printText:andMore:) 
      withObject:@"Cake" 
      withObject:@"More Cake"] 
5
@selector(printText:andMore:) 
+4

спасибо, но как бы я указал аргументы @ «Cake» и @ «More Cake»? – fuzzygoat

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

Существует '-performSelector: withObject: withObject:' и '-performSelector: withObject: afterDelay:', но сочетание двух не существует. – kennytm

+0

Вы правы. Я копировал/вставлял и делал ошибку. Хорошее место – pheelicks

1

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

@selector(printText:andMore:) 

Вы называете его

performSelector:withObject:withObject. 

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

14

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

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

+1

Те вещи, которые вы называете функциями, на самом деле называются методами. Не только в Objective-C, но и во всех серьезных языках программирования это различие сделано. Если быть точным: как только эта вещь привязана к объекту, это метод. Стоя в одиночку, это называется функцией. – Jacque

+0

Благодарим за информацию? – aqua

+0

В общем случае я использую словарь для передачи парм. Вы не зависимы от заказов, и вы можете легко иметь дополнительные парм и т. Д. –

17

В качестве альтернативы для 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); 
+1

Это именно то, что я искал. Мне нужно было иметь возможность передавать параметры по ссылке и не мог понять, как это сделать с помощью функции performSelector. Я выяснил это с помощью NSInvocation, но я продолжал получать ошибки malloc. Это сделало именно то, что мне было нужно. –

2

Конкретизируя Ben-Uri's answer, который может быть записан путь короче.

E.g. вызова метода 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); 
+0

На основе этого сообщения SO (http://stackoverflow.com/questions/10952996/why-does-this-code-give-exc-bad-access-using-imp) у вас возникнут проблемы с памятью, если у вас есть ARC включен. – stuckj

4

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

#import <objc/message.h> // objc_msgSend 
... 
((void (*)(id, SEL, Type1, Type2, Type3))objc_msgSend)(target, a_selector, obj1, obj_of_type2, obj_of_type3); 
Смежные вопросы