2012-11-02 11 views

Odpowiedz

7

To działa, ale jest nieco anty-wzorem. To, co mógłbym zrobić, to zgłoszenie błędu, jeśli wątek, do którego wywołana jest metoda, nie jest głównym wątkiem. Obowiązkiem osoby dzwoniącej jest upewnienie się, że metody są wywoływane na właściwych wątkach, tego rodzaju hacki tylko zachęcają do brzydkiego kodu. Poza tym, jeśli polegasz na tym, nagle podwajasz wysyłkę wiadomości nad każdym razem, gdy wywołujesz tę metodę.

Jeśli naprawdę nie mogę zmienić zachowanie rozmówcy, można spróbować wykonać następujące czynności:

-(void)methodToBeRunOnMainThreadWithObj:(id)object { 
    dispatch_sync(dispatch_get_main_queue(), ^{ 
     // code goes here 
    }); 
} 

spowoduje to cały kod wewnątrz bloku wysyłkowy być wykonywane w głównym wątku, a metoda nie wróci, dopóki jest kompletny. Jeśli chcesz, aby metoda natychmiast powróciła, możesz zamiast tego użyć dispatch_async. Jeśli używasz dispatch_sync, możesz użyć tej sztuczki nawet w przypadku metod, które mają nieważne typy zwrotu.

Ten kod ma także dodatkową zaletę, że obsługuje metody z argumentami niezwiązanymi z obiektami (int itd.). Obsługuje również metody z dowolną liczbą argumentów, podczas gdy performSelector:withObject: i jego metody rodzeństwa obsługują tylko ograniczoną liczbę argumentów. Alternatywą jest ustawienie obiektów NSInvocation i to jest problem.

Pamiętaj, że wymaga to Grand Central Dispatch (GCD) na twojej platformie.

+0

+1 dla niebezpiecznej alternatywy – justin

3

_cmd spedycja jest w porządku, dopóki selektor określony przez _cmd odpowiada definicji/podpis określonej w dokumentacji: „Metoda nie powinien mieć znaczącą wartość powrotną i podjąć jeden argument typu ID, lub nie argumenty.". Jeśli nie pasuje, to powinieneś założyć niezdefiniowane zachowanie. I aby być w 110% bezpiecznym i trzymać się abstrakcyjnej maszyny, typem zwracanym powinno być id (lub jakiś typ objc), a wynik nie powinien zwracać odniesienia do posiadania.

+1

+1 za odnotowanie ograniczeń. W mojej odpowiedzi zignorowałem problem typu return, ponieważ oryginalna metoda w pytaniu to "void", ale OP wydaje się szukać ogólnego rozwiązania, a 'performSelector' nie jest nim. – yfrancis

+0

@yfrancis początkowo unikałem także wymieniania typu zwrotu, ale dodałem trochę o tym w edycji. – justin

Powiązane problemy