2009-05-28 13 views
157

Czy można łatwo opóźnić wywołanie metody przez 1 sekundę?Jak mogę opóźnić wywołanie metody na 1 sekundę?

Mam UIImageView, który reaguje na wydarzenie dotykowe. Po wykryciu dotyku w aplikacji pojawiają się animacje. Po jednej sekundzie chcę wywołać inną metodę. W takim przypadku nie mogę użyć selektora animationDidStop.

+0

Nie są certai na kilka sposobów na to, jednym z nich może być po prostu użycie trybu uśpienia() w celu zawieszenia programu/wątku na kilka milisekund, ** jednak ** Myślę, że możesz chcieć powiedzieć nam, co dokładnie próbujesz osiągnąć to przez to? Mam na myśli, jaki jest twój rzeczywisty problem? Idea opóźnienia wywołania metody wydaje się być "rozwiązaniem", które nie brzmi zbyt dobrze, by być uczciwym. Powiedz nam więcej o scenariuszu, który masz na myśli. – none

Odpowiedz

243
performSelector:withObject:afterDelay: 

Document Reference

+6

To jest poprawna odpowiedź. Zobacz http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelector:withObject:afterDelay: – harms

+1

Doskonała odpowiedź! Działa świetnie. – Thanks

+2

to, co można uzyskać, przedstawiając ostrożnie sformułowane pytanie w pierwszej kolejności :-) – none

-37

UWAGA: spowoduje to przerwanie całej nici, a nie tylko jednej metody.
Zadzwoń do trybu uśpienia/oczekiwania/zatrzymania przez 1000 ms tuż przed wywołaniem metody?

Sleep(1000); // does nothing the next 1000 mSek 

Methodcall(params); // now do the real thing 

Edit: Powyższa odpowiedź odnosi się do ogólnego pytanie „Jak mogę opóźnić wywołanie metody przez 1 sekundę?”, Który został pytanie zadane w czasie odpowiedzi (to rzeczywiście odpowiedź została udzielona w ciągu 7 minuty oryginalnego pytania :-)). Brak informacji dano o języku w tym czasie, więc uprzejmie zatrzymać skarżenie na temat właściwego sposobu korzystania spać Xcode og brak klas ...

+0

który zatrzymałby tylko wszystko w aplikacji, prawda? – Thanks

+0

Tylko w bieżącym wątku pozostałe wątki będą nadal działać. –

+3

Geez. Rozumiem, dlaczego to było kilkakrotnie odrzucane, ale kto do cholery widział to w -27 i uznał, że potrzebuje innego? Czy -3 lub coś nie ma znaczenia. Dlaczego po prostu nie edytujesz odpowiedzi, by powiedzieć "to wstrzyma całą twoją nitkę" lub coś, zamiast odrzucać ją ludziom? –

123

Najlepszy sposób, aby zrobić to :

[self performSelector:@selector(YourFunctionName) 
      withObject:(can be Self or Object from other Classes) 
      afterDelay:(Time Of Delay)]; 

można również przekazać zero jako parametrObject.

przykład:

[self performSelector:@selector(subscribe) withObject:self afterDelay:3.0 ]; 
+3

Dlaczego miałbyś przekazać sobie na własny rachunek? – Eric

+2

I dlaczego miałbyś przekazać zmienną do metody, która przyjmuje zero argumentów? – hellozimi

17

można użyć do wykonania selektor po sposób opóźnienia 0,1 sekundy jest połączenie dla tego kolejnego kodu do tego celu.

[self performSelector:@selector(InsertView) withObject:nil afterDelay:0.1]; 
167

Można również używać blokady

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 
    [object method]; 
}); 

Większość czasu będziesz chciał użyć dispatch_get_main_queue, chociaż jeśli nie ma UI w metodzie można użyć global queue.

Edit:

Swift 3 wersja:

DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 
    object.method() 
} 

Podobnie DispatchQueue.global().asyncAfter(... może być również dobrym rozwiązaniem.

+0

Znaleziono rozwiązanie to być łatwiejsze niż performSelector podczas mieszania prostą C i ObjC –

+1

Niestety dispatch_get_current_queue jest przestarzała od iOS6 – chrisben

+3

Updated używać dispatch_get_main_queue zamiast dispatch_get_current_queue – mcfedr

8

Można także:

[UIView animateWithDuration:1.0 
       animations:^{ self.view.alpha = 1.1; /* Some fake chages */ } 
       completion:^(BOOL finished) 
{ 
    NSLog(@"A second lapsed."); 
}]; 

tym przypadku musisz udawać pewne zmiany do jakiegoś celu dostać pracę animacji. To naprawdę hacky, ale uwielbiam te oparte na blokach. Lub załóż odpowiedź @mcfedr poniżej.


waitFor(1.0,^
{ 
    NSLog(@"A second lapsed"); 
}); 

typedef void (^WaitCompletionBlock)(); 
void waitFor(NSTimeInterval duration, WaitCompletionBlock completion) 
{ 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC), 
        dispatch_get_main_queue(),^
    { completion(); }); 
} 
+0

Nie jestem pewien, ale myślę, że pierwsza proponowana opcja może mieć skutki uboczne, o których użytkownicy powinni wiedzieć, np. Blokowanie interakcji użytkownika części interfejsu użytkownika. Instynktem jest to, że spowodowałoby to niepotrzebne obciążenie procesora lub inne zasoby, ale nie sprawdziłem. –

7

Można to zrobić

[self performSelector:@selector(MethodToExecute) withObject:nil afterDelay:1.0 ]; 
20

Istnieje już wiele odpowiedzi i wszystkie są prawidłowe. Jeśli chcesz użyć modelu dispatch_after, powinieneś poszukać fragmentu, który znajduje się wewnątrz Code Snippet Library w prawym dolnym rogu (gdzie możesz wybrać elementy UI).

enter image description here

więc wystarczy zadzwonić ten fragment pisząc wysyłkę w kodzie:

enter image description here

0

Jest Swift 3 rozwiązanie od sprawdzanego rozwiązanie:

self.perform(#selector(self.targetMethod), with: self, afterDelay: 1.0) 

I jest metoda

@objc fileprivate func targetMethod(){ 

} 
1

Swift 2.x

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))) 
dispatch_after(delayTime, dispatch_get_main_queue()) { 
print("do some work") 
} 

Swift 3.x - & - szybkie 4

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { 
    print("do some work") 
} 
0

Zastosowanie Swift 3

perform(<Selector>, with: <object>, afterDelay: <Time in Seconds>) 
Powiązane problemy