2011-08-17 9 views
16

Potrzebuję zapisać sposób, aby powiedzieć: "iOS, chcę, aby ta metoda została wykonana a.s.a.p., ale NIE w tej iteracji pętli uruchomienia.Najpierw w następnym, ale proszę nie w tym." Dziękuję. "Jak wywołać metodę a.s.a.p. ale najwcześniej w kolejnej iteracji pętli?

Teraz jestem zawsze robi to tak:

[self performSelector:@selector(doSomethingInNextRunLoop) withObject:nil afterDelay:0]; 
[self doSomeOtherThings]; 

Przy założeniu, że -doSomeOtherThings zawsze będą wykonywane przed -doSomethingInNextRunLoop.

Dokumentacja mówi:

Określanie opóźnienie 0 niekoniecznie powodować selektor być wykonywane natychmiast. Selektor nadal znajduje się w kolejce w pętli uruchamiania wątku i wykonuje się tak szybko, jak to możliwe.

Więc w zasadzie może się zdarzyć, że metoda jest wywoływana natychmiast, jak gdybym właśnie wysłał wiadomość bezpośrednią, powodując -doSomethingInNextRunLoop być wykonywane przed -doSomeOtherThings?

Jak mogę się całkowicie upewnić, że będzie to nazywane a.s.a.p. ale NIGDY nigdy w tej samej pętli iteracji run?

Aby wyjaśnić sformułowanie: Z pętli uruchamiania mam na myśli główny wątek i iterację, w której muszą wrócić wszystkie metody, aż wątek będzie gotowy na nowe zdarzenia.

Odpowiedz

9

Jeśli obawiasz się, że firma Apple może pewnego dnia opóźnić o 0, zawsze możesz określić opóźnienie wynoszące 1e-37 lub więcej. Chociaż dokumentacja dla performSelector:withObject:afterDelay: może być łatwo odczytana, aby zagwarantować, że selektor będzie zawsze zaplanowany na kolejną iterację pętli.

Jeśli obawiasz się, że firma Apple może pewnego dnia opóźnić sprawę specjalną o mniej niż pewną dowolną dolną granicę, zawsze możesz spróbować użyć NSROunLoop's performSelector:target:argument:order:modes:, którą dokumentacja konkretnie stwierdza, zaplanuje wykonanie dla następnej iteracji pętli uruchamiania.

+0

Znakomity! Kategoria, która to ułatwi, miałaby sens. – openfrog

0

Z pewnością to właśnie robisz;

[self doSomeOtherThings]; 
[self performSelector:@selector(doSomethingInNextRunLoop) withObject:nil afterDelay:0]; 

Który gwarantuje żądaną kolejność wykonania.

+1

To nie zawsze jest wygodne (lub możliwe), aby zmienić kod w ten sposób w przypadkach bardziej złożonych niż ten trywialny przykład wykorzystywane do ilustracji. – Anomie

+0

Niezupełnie. Istnieją powody, dla których należy wykonywać operacje w iteracji pętli NEXT. Jeden z nich: Pozwalanie na odświeżanie się interfejsu użytkownika. Poprawienie postrzeganej wydajności. Wśród wielu innych. Poza tym Anomie ma rację. – openfrog

+0

Na pewno reakcja Anomie uderza w gwóźdź w głowę, po prostu zwracam uwagę, że w niektórych przypadkach zmiana układu kodu również może rozwiązać problem. Trochę jak blok pisarzy, czasami deweloperzy odkładają słuchawkę na rozwiązywanie problemu w określony sposób, gdy w rzeczywistości jest plan boczny B. FWIW Nie jestem świadomy KAŻDEGO wystąpienia, w którym standard performSelector: withObject: afterDelay: 0 blokowanie i częste używanie techniki optymalizacji kodu interfejsu użytkownika napisanego przez innych. – Roger

1

Myślę, że wnioski z czytania dokumentacji są błędne.

Więc w zasadzie może się zdarzyć, że metoda jest wywoływana natychmiast, jak gdybym właśnie wysłał wiadomość bezpośrednią

nr Część dokumentacji cytujesz mówi, że selektor jest zawsze w kolejce na uruchom pętlę, bez względu na wszystko. Więc nigdy nie zostanie wykonane jako bezpośrednia wiadomość.

Pierwsze zdanie z "niekoniecznie" może być nieco mylące, ale sądzę, że drugie zdanie powinno naprawdę wyjaśnić, że to, czego się obawiasz, nie jest możliwe.

+0

Mam nadzieję, że masz rację, ponieważ założę się, że wielu ludzi zależy od tego, czy będzie w kolejce do następnej iteracji. Mimo to jest pewna niepewność. – openfrog

6

Dość banalna użyciu GCD (Grand Central Dispatch):

dispatch_async (dispatch_get_main_queue(), ^{ 
    NSLog (@"This stuff runs in the next iteration of the main run loop"); 
}); 
Powiązane problemy