Czy istnieje sposób na wywołanie bloku z prymitywnym parametrem po opóźnieniu, np. Użycie, performSelector:withObject:afterDelay:
ale z argumentem takim jak int
/ double
/ float
?
735
Czy istnieje sposób na wywołanie bloku z prymitywnym parametrem po opóźnieniu, np. Użycie, performSelector:withObject:afterDelay:
ale z argumentem takim jak int
/ double
/ float
?
Odpowiedzi:
Myślę, że szukasz
dispatch_after()
. Wymaga, aby Twój blok nie akceptował żadnych parametrów, ale możesz po prostu pozwolić, aby blok przechwycił te zmienne z twojego zasięgu lokalnego.Więcej: https://developer.apple.com/documentation/dispatch/1452876-dispatch_after
źródło
dispatch_time(DISPATCH_TIME_NOW, 10ull * NSEC_PER_SEC)
fragment jest paskudny. Czy nie ma na to czystszego sposobu?dispatch_get_current_queue()
zawsze zwraca kolejkę, z której uruchamiany jest kod. Kiedy więc ten kod zostanie uruchomiony z głównego wątku, blok zostanie również wykonany w głównym wątku.dispatch_get_current_queue()
jest przestarzałeMożesz użyć,
dispatch_after
aby wywołać blok później. W Xcode zacznij pisaćdispatch_after
i naciśnij przyciskEnter
autouzupełniania, aby:Oto przykład z dwoma zmiennoprzecinkowymi jako „argumentami”. Nie musisz polegać na żadnym rodzaju makra, a cel kodu jest dość jasny:
Swift 3, Swift 4
Swift 2
Cel C
źródło
NSEC_PER_SEC * 0.5
działałoby tak samo jakNSEC_PER_MSEC * 500
. Chociaż słusznie zauważysz, żedispatch_time
oczekuje się 64-bitowej liczby całkowitej, oczekuje się, że wartość będzie wyrażona w nanosekundach.NSEC_PER_SEC
jest zdefiniowany jako1000000000ull
, a pomnożenie tego przez stałą zmiennoprzecinkową0.5
niejawnie wykonałoby arytmetykę zmiennoprzecinkową, dając500000000.0
, zanim zostanie jawnie rzutowane z powrotem na 64-bitową liczbę całkowitą. Tak więc użycie ułamka jest całkowicie dopuszczalneNSEC_PER_SEC
.Co powiesz na użycie wbudowanej biblioteki fragmentów kodu Xcode?
Aktualizacja dla Swift:
Wiele głosów zachęciło mnie do zaktualizowania tej odpowiedzi.
Wbudowana biblioteka fragmentów kodu Xcode ma
dispatch_after
tylkoobjective-c
język. Ludzie mogą również tworzyć własne niestandardowe fragmenty koduSwift
.Napisz to w Xcode.
Przeciągnij ten kod i upuść go w obszarze biblioteki fragmentów kodu.
Na dole listy fragmentów kodu pojawi się nowy obiekt o nazwie
My Code Snippet
. Edytuj to dla tytułu. Aby uzyskać sugestię podczas wpisywania Xcode, wypełnijCompletion Shortcut
.Aby uzyskać więcej informacji, zobacz CreatingaCustomCodeSnippet .
Zaktualizuj Swift 3
Przeciągnij ten kod i upuść go w obszarze biblioteki fragmentów kodu.
źródło
Rozwijając odpowiedź Jaime Cham stworzyłem kategorię NSObject + Blocks, jak poniżej. Czułem, że te metody lepiej pasują do istniejących
performSelector:
metod NSObjectNSObject + Blocks.h
NSObject + Blocks.m
i użyj tak:
źródło
delay
Powinny byćNSTimeInterval
(co jestdouble
).#import <UIKit/UIKit.h>
nie jest potrzebne. I nie rozumiem, dlaczego- (void)performBlock:(void (^)())block;
może być przydatny, więc można go usunąć z nagłówka.Być może prostsze niż przechodzenie przez GCD, gdzieś w klasie (np. „Util”) lub w kategorii na obiekcie:
Więc użyć:
źródło
Dla Swift stworzyłem funkcję globalną, nic specjalnego, przy użyciu tej
dispatch_after
metody. Podoba mi się to bardziej, ponieważ jest czytelny i łatwy w użyciu:Którego możesz użyć w następujący sposób:
źródło
after
. Następnie możesz napisać:after(2.0){ print("do somthing") }
Oto moje 2 centy = 5 metod;)
Lubię enkapsulować te szczegóły i niech AppCode powie mi, jak dokończyć zdania.
źródło
PerformSelector: WithObject zawsze pobiera obiekt, więc w celu przekazania argumentów takich jak int / double / float itp ... Możesz użyć czegoś takiego.
// NSNumber jest obiektem ..
W ten sam sposób możesz użyć [NSNumber numberWithInt:] itp. .... a w metodzie odbierającej możesz przekonwertować liczbę na swój format jako [liczba int] lub [liczba podwójna].
źródło
Funkcja dispatch_after wysyła obiekt bloku do kolejki wysyłki po upływie określonego czasu. Użyj poniższego kodu, aby wykonać niektóre czynności związane z interfejsem użytkownika po 2,0 sekundach.
W swift 3.0:
źródło
mainQueue,
zamiastmainQueue)
Oto Swift 3 sposób na kolejkowanie pracy po opóźnieniu.
źródło
Oto przydatny pomocnik, który zapobiega nawracaniu połączeń GCD w kółko:
Teraz po prostu opóźniasz kod w głównym wątku w następujący sposób:
Jeśli chcesz opóźnić kod do innego wątku :
Jeśli wolisz Framework, który ma również kilka przydatnych funkcji, sprawdź HandySwift . Możesz dodać go do swojego projektu za pośrednictwem Kartaginy, a następnie użyć go dokładnie tak, jak w powyższych przykładach:
źródło
Jest ładny w frameworku BlocksKit.
BlocksKit
(i klasa)
BBlocksKit.m
źródło
W swift 3 możemy po prostu użyć funkcji DispatchQueue.main.asyncAfter, aby uruchomić dowolną funkcję lub akcję po upływie „n” sekund. Tutaj w kodzie ustawiliśmy opóźnienie po 1 sekundzie. Wywołujesz dowolną funkcję wewnątrz ciała tej funkcji, która uruchomi się z opóźnieniem 1 sekundy.
źródło
Xcode 10.2 i Swift 5 i nowsze wersje
źródło
Możesz albo zawinąć argument we własną klasę, albo zawinąć wywołanie metody w metodę, która nie musi być przekazywana w typie pierwotnym. Następnie wywołaj tę metodę po opóźnieniu i w ramach tej metody wykonaj selektor, który chcesz wykonać.
źródło
Oto jak możesz uruchomić blok po opóźnieniu w Swift:
Jest zawarty jako standardowa funkcja w moim repozytorium .
źródło
Swift 3 i Xcode 8.3.2
Ten kod pomoże ci, dodam też wyjaśnienie
źródło
Uważam, że autor nie pyta, jak czekać na ułamek czasu (opóźnienie), ale zamiast tego, jak przekazać skalar jako argument selektora (withObject :), a najszybszym sposobem we współczesnym celu C jest:
twój selektor musi zmienić parametr na NSNumber i pobrać wartość za pomocą selektora takiego jak floatValue lub doubleValue
źródło