2011-08-13 7 views
5

Dlaczego generowane są ostrzeżenia podczas wywoływania metod niezadeklarowanych w interfejsie klasy przy użyciu konwencjonalnych środków, ale nie podczas wywoływania metod za pomocą @selector? Czy to dlatego, że selektory mogą być wykonywane przez innego rozmówcę niż samo?Dlaczego Xcode nie skarży się na niezadeklarowane metody podczas korzystania z @selector?

Na przykład:

-(void) doStuff 
{ 
    [self doNow]; // Warning: instance method not found 
    SEL sel = @selector(doNow); // no warnings 
} 

-(void) doNow {} // this method is not declared in the interface 

Odpowiedz

13

W "nielegalna Selector" Ostrzeżenie jest domyślnie wyłączona. Nie wiem dlaczego. Możesz go ponownie włączyć w Ustawieniach kompilacji.

Dokumentacja dla tej ustawieniach brzmi:

Informuj jeśli „@selector (...)” wyrażenie odnoszące się do selektora nierejestrowanej znaleziono. Selektor jest uważany za niezadeklarowanego, jeśli żadna metoda o tej nazwie nie została zadeklarowana przed wyrażeniem "@ Selektor (...)", jawnie w deklaracji @interface lub @protocol, lub niejawnie w sekcji @implementacja. Ta opcja zawsze wykonuje sprawdzenia, gdy tylko zostanie znalezione wyrażenie "@ Selektor (...)", podczas gdy -Wselector wykonuje tylko swoje kontrole w końcowym etapie kompilacji. To również wymusza konwencję stylu kodowania, że ​​metody i selektory muszą być deklarowane przed użyciem. [GCC_WARN_UNDECLARED_SELECTOR, -Wundeclared selektor]

+1

+1 tylko dla dokumentacji. –

+0

Dziękuję. Wydaje się niespójne z Apple, aby ta opcja była domyślnie wyłączona. –

4

Podobny question zwrócono na SO kilka tygodni.

Jest to zasadniczo dlatego, że selektory są późno związane. Nie są wyświetlane aż do czasu wykonania. Istnieją opcje wymuszania weryfikacji podczas kompilacji. Pytanie, które łączyłem, zawiera więcej informacji na temat tego, jak możesz to zrobić.

2

Sposób @ Selektor działa domyślnie, to mówisz kompilatorowi; uwierz mi, mam tę metodę gdzieś w mojej klasie. Jest to ta sama koncepcja, jeśli użyjesz @class yourclassname zamiast importować plik .h, który zawiera klasę.

2

To dlatego, że kompilator musi znać sygnaturę metody, aby go (tzn [self doNow];) zadzwonić, ponieważ takie połączenie przekłada się na każdym wywołaniu objc_msgSend lub objc_msgSend_stret w zależności od tego, czy podpis metoda ma typ zwracanej z struct lub nie. (Pamiętaj o różnicy między selektorem (po prostu nazwa z dwukropkami w nim, ale bez typów) i podpisem (typami) metody.) Musi więc ostrzec, ponieważ może wywołać niewłaściwą funkcję, jeśli nie działa 'nie wiem.

Jednak uzyskanie selektora (@selector(...)) nie wymaga znajomości typów. Selektor jest po prostu nazwą i podałeś jego nazwę. Chodzi o to, do czego używasz selektora. Jeśli użyjesz go w performSelector:, również nie musisz znać typów, ponieważ ta metoda działa tylko w przypadku metod z typami argumentów i typów zwracanych, więc nie ma dwuznaczności. Dlatego nie ma potrzeby ostrzeżenia.

Powiązane problemy