2011-09-22 10 views
13

UIView ma metodę setNeedsDisplay, którą można wywołać kilka razy w tej samej pętli zdarzeń, bezpieczną wiedząc, że ponowne rysowanie nastąpi wkrótce i tylko raz.Czy istnieje prosty sposób (w Cocoa/iOS) do kolejkowania wywołania metody, aby uruchomić go raz w następnym uruchomieniu pętli?

Czy istnieje ogólny mechanizm tego rodzaju zachowania Kakao? Sposób mówienia: "Kolejkuj selektor tyle razy, ile chcesz, kiedy nadejdzie czas, selektor uruchomi się po wyczyszczeniu kolejki."

Wiem, że mógłbym to zrobić z jakimś śledzeniem stanu w moim celu lub z NSOperationQueue. Zastanawiam się tylko, czy brakuje mi lekkiego podejścia.

(Oczywiście, odpowiedź może być „Nie”).

+0

@Barious Użyłem UIKit jako przykładu, ale myślę, że pytanie dotyczy ogólnie Kakao, czyż nie? –

+0

Prawdopodobnie. Jeśli masz pewność, że każde podejście w systemie Mac OS X dotyczy Twojego pytania, dodaj tag kakao. –

Odpowiedz

12

setNeedsDisplay nie jest dobrym przykładem tego, co opisujesz, ponieważ faktycznie jest uruchamiany za każdym razem to nazwać. Po prostu ustawia flagę. Ale pytanie jest dobre.

Jednym z rozwiązań jest użycie NSNotificationQueue z NSNotificationCoalescingOnName.

Innym rozwiązaniem jest zbudowanie trampoliny do samodzielnego łączenia. Nie mam naprawdę dobrego bloga dla trampolin, ale oto przykład jednego (LSTrampoline). Nie jest trudno to zbudować, jeśli chcesz połączyć komunikaty przez pewien okres czasu. Kiedyś zbudował trampolina z forwardInvocation: podobne do tego:

- (void)forwardInvocation:(NSInvocation *)invocation { 
    [invocation setTarget:self.target]; 
    [invocation retainArguments]; 
    [self.timer invalidate]; 
    self.timer = [NSTimer scheduledTimerWithTimeInterval:self.timeout invocation:invocation repeats:NO]; 
} 

To rzeczywiście scala wszystkie wiadomości do obiektu w okresie czasu (nie tylko dopasowania messages). To wszystko, czego potrzebowałem do konkretnego problemu. Możesz jednak rozwinąć to, aby śledzić, które selektory są połączone, i sprawdzić swoje inwokacje, aby sprawdzić, czy pasują do siebie "dostatecznie".

Aby uzyskać to do uruchomienia na kolejnej pętli zdarzeń, wystarczy ustawić limit czasu na 0.

Ciągle czyli blog o trampoliny. Wymagane szyling: My upcoming book obejmuje trampoliny w rozdziale 4 i rozdziale 20.

+2

Fantastyczna odpowiedź i myślę, że NSNotificationCoalescingOnName jest dokładnie tym, czego szukałem. :-) –

6
[NSObject cancelPreviousPerformRequestsWithTarget:self 
             selector:@selector(doTheThing:) 
              object:someObject]; 
[self performSelector:@selector(doTheThing:) 
      withObject:someObject 
      afterDelay:0]; 

To nie jest dokładnie tak, jak to robi UIView ponieważ setNeedsDisplay prostu ustawia flagę i wewnętrzna UIView mechanizm pilnuje aby zadzwonić drawRect: Po skonfigurowaniu środowisko rysowania, ale jest to ogólny sposób i nie wymaga specjalnego śledzenia stanu w klasie.

+1

Zauważ, że wywołanie 'cancelPreviousPerformRequest ...' może być bardzo wolne. W wielu przypadkach jest to w porządku, ale jeśli jest wywoływany bardzo często, może to stanowić problem. –

Powiązane problemy