it-swarm.com.de

Ziel-C: Aufruf von Selektoren mit mehreren Argumenten

In MyClass.m habe ich definiert

- (void) myTest: (NSString *) withAString{
    NSLog(@"hi, %@", withAString);
}

und die entsprechende Erklärung in MyClass.h. Später möchte ich anrufen

[self performSelector:@selector(mytest:withAString:) withObject: mystring];

in MyClass.m wird jedoch ein Fehler angezeigt, der dem folgenden ähnelt: * Beenden der App aufgrund einer nicht erfassten Ausnahme 'NSInvalidArgumentException', Grund: '* - [MyClass myTest: withAtring:]: Unbekannter Selektor an Instanz 0xe421f0 gesendet.'

Ich habe einen einfacheren Fall mit einem Selektor ausprobiert, bei dem keine Argumente verwendet wurden, die eine Zeichenfolge an die Konsole druckten, und der gut funktionierte. Was ist los mit dem Code und wie kann ich das beheben? Vielen Dank.

139
Stu

Ihre Methodensignatur lautet:

- (void) myTest:(NSString *)

withAString ist zufällig der Parameter (der Name ist irreführend, er scheint Teil der Signatur des Selektors zu sein).

Wenn Sie die Funktion folgendermaßen aufrufen:

[self performSelector:@selector(myTest:) withObject:myString];

Es wird klappen.

Wie die anderen Poster bereits vorgeschlagen haben, möchten Sie die Methode möglicherweise umbenennen:

- (void)myTestWithAString:(NSString*)aString;

Und Ruf an:

[self performSelector:@selector(myTestWithAString:) withObject:myString];
135

In Objective-C besteht die Signatur eines Selektors aus:

  1. Der Name der Methode (in diesem Fall wäre es "myTest") (erforderlich)
  2. Ein ':' (Doppelpunkt) nach dem Methodennamen, wenn die Methode eine Eingabe hat.
  3. Ein Name und ':' für jede weitere Eingabe.

Selektoren haben keine Kenntnis von:

  1. Die Eingabetypen
  2. Der Rückgabetyp der Methode.

Hier ist eine Klassenimplementierung, bei der die Methode performMethodsViaSelectors die anderen Klassenmethoden über Selektoren ausführt:

@implementation ClassForSelectors
- (void) fooNoInputs {
    NSLog(@"Does nothing");
}
- (void) fooOneIput:(NSString*) first {
    NSLog(@"Logs %@", first);
}
- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second {
    NSLog(@"Logs %@ then %@", first, second);
}
- (void) performMethodsViaSelectors {
    [self performSelector:@selector(fooNoInputs)];
    [self performSelector:@selector(fooOneInput:) withObject:@"first"];
    [self performSelector:@selector(fooFirstInput:secondInput:) withObject:@"first" withObject:@"second"];
}
@end

Die Methode, für die Sie einen Selektor erstellen möchten, verfügt über eine einzige Eingabe, sodass Sie einen Selektor wie folgt erstellen würden:

SEL myTestSelector = @selector(myTest:);
308
Shane Arney

@ Shane Arney

performSelector:withObject:withObject:

Möglicherweise möchten Sie auch erwähnen, dass diese Methode nur für die Übergabe von maximal 2 Argumenten gedacht ist und nicht verzögert werden kann. (sowie performSelector:withObject:afterDelay:).

irgendwie seltsam, dass Apple nur 2 Objekte zum Senden unterstützt und es nicht allgemeiner gemacht hat.

13
Lirik

Ihr Code hat zwei Probleme. Einer wurde identifiziert und beantwortet, der andere nicht. Das erste war, dass Ihrem Selektor der Name seines Parameters fehlte. Selbst wenn Sie dies beheben, wird in der Zeile dennoch eine Ausnahme ausgelöst, vorausgesetzt, Ihre überarbeitete Methodensignatur enthält noch mehr als ein Argument. Angenommen, Ihre überarbeitete Methode wird wie folgt deklariert:

-(void)myTestWithString:(NSString *)sourceString comparedTo:(NSString *)testString ;

Das Erstellen von Selektoren für Methoden, die mehrere Argumente annehmen, ist vollkommen gültig (z. B. @selector (myTestWithString: compareTo :)). Mit der performSelector-Methode können Sie jedoch nur einen Wert an myTest übergeben, der leider mehr als einen Parameter enthält. Es wird ein Fehler auftreten und Ihnen mitteilen, dass Sie nicht genügend Werte angegeben haben.

Sie können Ihre Methode jederzeit neu definieren, um eine Sammlung als einzigen Parameter zu übernehmen:

-(void)myTestWithObjects:(NSDictionary *)testObjects ;

Es gibt jedoch eine elegantere Lösung (die kein Refactoring erfordert). Die Antwort ist, NSInvocation zusammen mit den Methoden setArgument:atIndex: Und invoke zu verwenden.

Ich habe geschrieben ein Artikel, einschließlich eines Codebeispiels , wenn Sie weitere Details wünschen. Der Schwerpunkt liegt auf dem Threading, die Grundlagen gelten jedoch weiterhin.

Viel Glück!

7
Zack

Ihre Methodensignatur macht keinen Sinn, sind Sie sicher, dass es kein Tippfehler ist? Mir ist nicht klar, wie es überhaupt kompiliert wird, obwohl Sie vielleicht Warnungen erhalten, die Sie ignorieren?

Wie viele Parameter sollte diese Methode annehmen?

3
Rob Napier

Denken Sie, die Klasse sollte definiert werden als:

- (void) myTestWithSomeString:(NSString *) astring{
    NSLog(@"hi, %s", astring);
}

Sie haben nur einen einzigen Parameter, daher sollten Sie nur einen einzigen haben:

Vielleicht möchten Sie auch% @ in Ihrem NSLog verwenden - es ist nur eine gute Angewohnheit, sich darauf einzulassen - und dann jedes Objekt ausschreiben - nicht nur Strings.

2
Grouchal

iOS-Benutzer erwarten auch eine automatische Groß- und Kleinschreibung: In einem Standardtextfeld wird der erste Buchstabe eines Satzes in einer Sprache, bei der die Groß- und Kleinschreibung beachtet wird, automatisch großgeschrieben.

Sie können entscheiden, ob Sie solche Funktionen implementieren möchten oder nicht. Es gibt keine spezielle API für die gerade aufgelisteten Funktionen, daher ist deren Bereitstellung ein Wettbewerbsvorteil.

Apple-Dokument besagt, dass für diese Funktion und einige andere erwartete Funktionen in einer benutzerdefinierten Tastatur keine API verfügbar ist. Sie müssen also Ihre eigene Logik herausfinden, um dies zu implementieren.

0
Kannan Prasad