Objective-C: wywołanie selektorów z wieloma argumentami

W MyClass.m, zdefiniowałem

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

Oraz odpowiednią deklarację w MyClass.h . Później chcę zadzwonić

[self performSelector:@selector(mytest:withAString:) withObject: mystring];
W MyClass.m ale dostaję błąd podobny do * zakończenie aplikacji z powodu nieuwzględnionego wyjątku "NSInvalidArgumentException", powód: '* -[MyClass myTest: withAtring:]: nierozpoznany selektor wysłany do instancji 0xe421f0 '

Próbowałem prostszego przypadku z selektorem, który nie wziął żadnych argumentów, które drukowane ciąg do konsoli i że działa dobrze. Co to jest błąd w kodzie i jak go naprawić? Dzięki.

Author: Stu, 2009-06-19

7 answers

Twój podpis metody to:

- (void) myTest:(NSString *)

Z parametrem (nazwa jest myląca, wygląda na to, że jest częścią podpisu selektora).

Jeśli wywołasz funkcję w ten sposób:

[self performSelector:@selector(myTest:) withObject:myString];
To zadziała.

Ale, jak sugerowały inne plakaty, możesz zmienić nazwę Metody:

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

I wywołanie:

[self performSelector:@selector(myTestWithAString:) withObject:myString];
 133
Author: Lyndsey Ferguson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-15 15:52:16

W Objective-C podpis selektora składa się z:

  1. nazwa metody (w tym przypadku będzie to 'mytest') (wymagane)
  2. a ':' (dwukropek) po nazwie metody, jeśli metoda ma Dane wejściowe.
  3. Nazwa i": "dla każdego dodatkowego wejścia.

Selektory nie mają wiedzy o:

  1. typy wejść
  2. Typ zwracanej metody.

Oto Implementacja klasy, w której metoda performMethodsViaSelectors wykonuje inne metody klasy za pomocą selektorów:

@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

Metoda, dla której chcesz utworzyć selektor, ma jedno wejście, więc utworzysz dla niej selektor w następujący sposób:

SEL myTestSelector = @selector(myTest:);
 300
Author: Shane Arney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-07 20:20:48

@Shane Arney

performSelector:withObject:withObject:

Możesz również wspomnieć, że ta metoda służy tylko do przekazywania maksymalnie 2 argumentów i nie można jej opóźnić. (np. performSelector:withObject:afterDelay:).

Trochę dziwne, że apple obsługuje tylko 2 obiekty do wysłania i nie czyni go bardziej ogólnym.

 13
Author: Lirik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-05 13:10:38

Twój kod ma dwa problemy. Jeden został zidentyfikowany i odpowiedział, ale drugi nie. po pierwsze, twój selektor nie podał nazwy swojego parametru. Jednak nawet jeśli to naprawisz, linia nadal będzie wywoływać wyjątek, zakładając, że poprawiona sygnatura metody nadal zawiera więcej niż jeden argument. Załóżmy, że Twoja poprawiona metoda jest zadeklarowana jako:

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

Tworzenie selektorów dla metod pobierających wiele argumentów jest całkowicie poprawne (np. @selektor (myTestWithString: comparedTo:)). Jednak metoda performSelector pozwala przekazać tylko jedną wartość do myTest, która niestety ma więcej niż jeden parametr. Spowoduje to błąd i powie Ci, że nie podałeś wystarczającej ilości wartości.

Zawsze możesz przedefiniować metodę pobierania kolekcji, ponieważ jest to tylko parametr:

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

Istnieje jednak bardziej eleganckie rozwiązanie (które nie wymaga refaktoryzacji). Odpowiedzią jest użycie NSInvocation, wraz z jego setArgument:atIndex: i invoke metody.

Napisałem Artykuł, w tym przykład kodu , Jeśli chcesz więcej szczegółów. Skupiamy się na gwintowaniu, ale nadal obowiązują podstawy.

Powodzenia!
 7
Author: Zack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-18 15:19:26

Twój podpis metody nie ma sensu, jesteś pewien, że to nie literówka? Nie wiem jak to się w ogóle kompiluje, chociaż może dostajesz ostrzeżenia, które ignorujesz?

Ile parametrów oczekujesz od tej metody?

 3
Author: Rob Napier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 14:24:29

} klasa powinna być zdefiniowana jako:

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

Masz tylko jeden parametr, więc powinieneś mieć tylko jeden:

Możesz też rozważyć użycie %@ w swoim NSLog-jest to po prostu dobry nawyk, aby wejść - wtedy napiszesz dowolny obiekt-nie tylko ciągi.

 2
Author: Grouchal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 14:23:52

Użytkownicy IOS również oczekują autocapitalizacji: w standardowym polu tekstowym, pierwsza litera zdania w języku uwzględniającym wielkość liter to automatycznie pisane wielkimi literami.

Możesz zdecydować, czy zaimplementować takie funkcje, nie ma dedykowane API dla każdej z wymienionych właśnie funkcji, dzięki czemu ich jest przewagą konkurencyjną.

Dokument Apple mówi, że nie ma dostępnego API dla tej funkcji i niektórych innych oczekiwanych funkcji w customkeyboard. więc musisz znaleźć własną logikę, aby to zaimplementować.

 0
Author: Kannan Prasad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-12 05:43:07