2010-02-19 20 views
25

Ich habe @selector heute zum ersten Mal verwendet und war nicht in der Lage zu erarbeiten, wie das Folgende zu tun? Wie würden Sie die @selector schreiben, wenn Sie mehr als ein Argument hätten?@selector - mit mehreren Argumenten?

Keine Argumente:

-(void)printText { 
    NSLog(@"Fish"); 
} 

[self performSelector:@selector(printText) withObject:nil afterDelay:0.25]; 

Einzel Argument:

-(void)printText:(NSString *)myText { 
    NSLog(@"Text = %@", myText); 
} 

[self performSelector:@selector(printText:) withObject:@"Cake" afterDelay:0.25]; 

Zwei Argumente:

-(void)printText:(NSString *)myText andMore:(NSString *)extraText { 
    NSLog(@"Text = %@ and %@", myText, extraText); 
} 

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

mehrere Argumente: (das heißt mehr als 2)

NSInvocation

+0

aktualisiert Antworten zu reflektieren, vielen Dank für all die Hilfe, sehr geschätzt. – fuzzygoat

+1

Ihre "Doppelargumente" haben keine Verzögerung – user102008

Antwort

35

 

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

Von der Documentation:

Dieses Verfahren ist das gleiche wie performSelector: außer dass Sie zwei Argumente für aSelector liefern können. aSelector sollte eine Methode identifizieren, die zwei Argumente vom Typ ID annehmen kann. Verwenden Sie für Methoden mit anderen Argumenttypen und Rückgabewerten NSInvocation.

so in Ihrem Fall würden Sie verwenden:

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

danke, aber wie würde ich die Argumente @ "Kuchen" und @ "Mehr Kuchen" angeben? – fuzzygoat

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

Es gibt '-performSelector: withObject: withObject:' und '-performSelector: withObject: afterDelay:', aber die Mischung der beiden existiert nicht. – kennytm

+0

Richtig du bist. Ich war Kopieren/Einfügen und machte einen Fehler. Guter Punkt – pheelicks

1

Wie KennyTM wies darauf hin, der Selektor Syntax ist

@selector(printText:andMore:) 

Sie nennen es mit

performSelector:withObject:withObject. 

.. Wenn Sie mehr Argumente oder andere Typen benötigen, müssen Sieverwenden

14

Ich hatte ein Problem, wo ich die afterDelay zusammen mit mehreren Argumente zu meiner @selector Methode verwenden musste. Lösung? Verwenden Sie eine Wrapper-Funktion!

Sage dies die Funktion I wollen zu @selector weitergeben müssen:

-(void)myFunct:(NSString *)arg1 andArg:(NSString *)arg2 andYetAnotherArg:(NSString *)arg3; 

Offensichtlich ich nicht einmal withObject: withObject: hier verwenden können, so, einen Wrapper machen!

-(void)myFunctWrapper:(NSArray *)myArgs { 
    [self myFunct:[myArgs objectAtIndex:0] andArg:[myArgs objectAtIndex:1] andYetAnotherArg:[myArgs objectAtIndex:2]]; 
} 

und verwenden Sie es, indem Sie:

NSArray *argArray = [NSArray arrayWithObjects:string1,string2,string3,nil]; 
[self performSelector:@selector(myFunctWrapper:) withObject:argArray afterDelay:1.0]; 

So kann ich mehrere Argumente haben kann und die Wähler mit Verzögerung verwenden.

+1

Die Dinge, die Sie Funktionen nennen, werden tatsächlich Methoden genannt. Nicht nur in Objective-C, sondern in allen ernsthaften Programmiersprachen wird diese Unterscheidung getroffen. Um genau zu sein: Sobald dieses Ding an einem Objekt hängt, ist es eine Methode. Allein stehend nennt man das eine Funktion. – Jacque

+0

Danke für die Info? – aqua

+0

Für den allgemeinen Fall verwende ich ein Wörterbuch, um die Parms zu bestehen. Sie sind nicht auftragsabhängig und Sie können problemlos optionale Parameter usw. verwenden. –

17

Als Alternative für NSInvocation, wenn Sie mehr als zwei Parameter haben, können Sie NSObject die Verwendung -methodForSelector: wie im folgenden Beispiel:

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

Dies ist genau das, wonach ich gesucht habe. Ich musste in der Lage sein, die Parameter per Referenz zu übergeben, und konnte nicht herausfinden, wie es mit performSelector gemacht wird. Ich habe es mit NSInvocation herausgefunden, aber ich habe immer wieder malloc-Fehler bekommen. Das hat genau das getan, was ich tun musste. –

2

Ausarbeiten auf Ben-Uri's answer, die Art und Weise kürzer geschrieben werden können.

z.

SEL selector = @selector(covertPoint:toView:); 
IMP method = [viewA methodForSelector:selector]; 
CGPoint pointInB = method(viewA, selector, pointInA, viewB); 
+0

Basierend auf diesem SO-Post (http://stackoverflow.com/questions/10952996/why-does-this-code-give-exc-bad-access-using-imp) werden Sie auf diese Weise Speicherprobleme haben, wenn Sie haben ARC aktiviert – stuckj

4

Eine weitere Option ist eine noch kürzere Syntax zu verwenden: die UIView Methode aufrufen - (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view kann wie folgt durchgeführt werden

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