Selektory w Objective-C?

122

Po pierwsze, nie jestem pewien, czy naprawdę rozumiem, czym jest selektor. W moim rozumieniu jest to nazwa metody i można ją przypisać do klasy typu „SEL”, a następnie uruchomić metody, takie jak respondToSelector, aby sprawdzić, czy odbiornik implementuje tę metodę. Czy ktoś może zaoferować lepsze wyjaśnienie?

Po drugie, do tego momentu mam następujący kod:

NSString *thing = @"Hello, this is Craig";

SEL sel = @selector(lowercaseString:);
NSString *lower = (([thing respondsToSelector:sel]) ? @"YES" : @"NO");
NSLog (@"Responds to lowercaseString: %@", lower);
if ([thing respondsToSelector:sel]) //(lower == @"YES")
    NSLog(@"lowercaseString is: %@", [thing lowercaseString]);

Jednak mimo że thingjest to wyraźnie rodzaj NSString i powinien odpowiadać na lowercaseString, nie mogę uzyskać warunku „respondsToSelector”, aby zwrócić „YES” ...

Craig
źródło
Chcesz przeczytać opis Selectora na stronie programistów Apple: Selektory .
lothar
14
Kurs Stanford CS193P przypisanie 1B? Mam dokładnie to samo pytanie! :)
Corstian Boerman

Odpowiedzi:

181

Musisz bardzo uważać na nazwy metod. W tym przypadku nazwa metody to po prostu „ lowercaseString”, a nie „ lowercaseString:” (zwróć uwagę na brak dwukropka). Dlatego jesteś NOzwracany, ponieważ NSStringobiekty odpowiadają na lowercaseStringwiadomość, ale nie na lowercaseString:wiadomość.

Skąd wiesz, kiedy dodać okrężnicę? Dodaj dwukropek do nazwy wiadomości, jeśli chcesz dodać dwukropek podczas jej wywoływania, co dzieje się, gdy przyjmuje jeden argument. Jeśli przyjmuje zero argumentów (jak w przypadku lowercaseString), nie ma dwukropka. Jeśli wymaga więcej niż jednego argumentu, musisz dodać dodatkowe nazwy argumentów wraz z ich dwukropkami, jak w compare:options:range:locale:.

Możesz również przejrzeć dokumentację i zauważyć obecność lub brak końcowego dwukropka.

Adam Rosenfield
źródło
12

Selektory są skutecznym sposobem odwoływania się do metod bezpośrednio w skompilowanym kodzie - kompilator jest tym, co faktycznie przypisuje wartość do SEL.

Inne zajęły się już drugą częścią twojego q, ':' na końcu pasuje do innego podpisu niż ten, którego szukasz (w tym przypadku ten podpis nie istnieje).

dstnbrkr
źródło
10

To dlatego, że chcesz @selector(lowercaseString), a nie @selector(lowercaseString:). Jest subtelna różnica: druga oznacza parametr (zwróć uwagę na dwukropek na końcu), ale - [NSString lowercaseString]nie przyjmuje parametru.

mipadi
źródło
5

W tym przypadku nazwa selektora jest nieprawidłowa. Dwukropek jest tutaj częścią sygnatury metody; oznacza to, że metoda przyjmuje jeden argument. Wierzę, że chcesz

SEL sel = @selector(lowercaseString);
mkb
źródło
3

Metoda NSString to lowercaseString(0 argumentów), a nie lowercaseString:(1 argument).

Nicholas Riley
źródło
1

Nie myśl o dwukropku jako o części nazwy funkcji, myśl o nim jako o separatorze, jeśli nie masz nic do rozdzielenia (brak wartości, którą można by przypisać do funkcji), nie potrzebujesz tego.

Nie jestem pewien, dlaczego, ale wszystkie te rzeczy OO wydają się być obce programistom Apple. Zdecydowanie sugerowałbym pobranie Visual Studio Express i zabawę z tym. Nie dlatego, że jeden jest lepszy od drugiego, po prostu jest to dobry sposób na przyjrzenie się problemom projektowym i sposobom myślenia.

Lubić

introspection = reflection
+ before functions/properties = static
- = instance level

Zawsze dobrze jest spojrzeć na problem w inny sposób, a programowanie jest ostateczną zagadką.


źródło
0

Z mojego zrozumienia dokumentacji Apple wynika, że ​​selektor reprezentuje nazwę metody, którą chcesz wywołać. Zaletą selektorów jest to, że można ich używać w przypadkach, gdy dokładna metoda jest różna. Jako prosty przykład możesz zrobić coś takiego:

SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];
moonman239
źródło
0

Zgodnie z dokumentami Apple: https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html

Selektor to nazwa używana do wybierania metody do wykonania dla obiektu lub unikalny identyfikator, który zastępuje nazwę podczas kompilacji kodu źródłowego. Sam selektor nic nie robi. Po prostu identyfikuje metodę. Jedyną rzeczą, która sprawia, że ​​nazwa metody selektora różni się od zwykłego ciągu, jest to, że kompilator upewnia się, że selektory są unikalne. To, co sprawia, że ​​selektor jest przydatny, to fakt, że (w połączeniu ze środowiskiem wykonawczym) działa jak dynamiczny wskaźnik funkcji, który dla danej nazwy automatycznie wskazuje na implementację metody odpowiedniej dla dowolnej klasy, z którą jest używany. Załóżmy, że masz selektor do uruchomienia metody i klas Dog, Athlete i ComputerSimulation (z których każda zaimplementowała przebieg metody).

Przykład: (lldb) punkt przerwania --set selector viewDidLoad

Spowoduje to ustawienie punktu przerwania we wszystkich implementacjach viewDidLoad w Twojej aplikacji. Więc selector jest rodzajem globalnego identyfikatora metody.

Adrian
źródło