Ich habe das iBook von Apple durchgesehen und konnte keine Definition davon finden:
Kann jemand die Struktur von dispatch_after
erklären?
dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>)
Ich habe das iBook von Apple durchgesehen und konnte keine Definition davon finden:
Kann jemand die Struktur von dispatch_after
erklären?
dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>)
Ich verwende dispatch_after
so oft, dass ich eine Top-Level-Hilfsfunktion geschrieben habe, um die Syntax zu vereinfachen:
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
Und jetzt kannst du so sprechen:
delay(0.4) {
// etwas machen
}
Wow, eine Sprache, in der du die Sprache verbessern kannst. Was könnte besser sein?
Scheint fast nicht mehr wert zu sein, sich damit zu befassen, jetzt wo sie die Aufrufsyntax verbessert haben:
func delay(_ delay:Double, closure:@escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
Eine klarere Vorstellung von der Struktur:
dispatch_after(when: dispatch_time_t, queue: dispatch_queue_t, block: dispatch_block_t?)
dispatch_time_t
ist ein UInt64
. Der dispatch_queue_t
ist tatsächlich als Alias für ein NSObject
definiert, aber Sie sollten einfach Ihre vertrauten GCD-Methoden verwenden, um Queues zu erhalten. Der Block ist ein Swift Closure. Speziell ist dispatch_block_t
definiert als () -> Void
, was äquivalent zu () -> ()
ist.
Beispielverwendung:
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
print("test")
}
BEARBEITEN:
Ich empfehle die Verwendung von @matt's wirklich schöner delay
Funktion.
BEARBEITEN 2:
In Swift 3 wird es neue Wrapper für GCD geben. Siehe hier: https://github.com/apple/swift-evolution/blob/master/proposals/0088-libdispatch-for-swift3.md
Das ursprüngliche Beispiel würde in Swift 3 wie folgt geschrieben werden:
let deadlineTime = DispatchTime.now() + .seconds(1)
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
print("test")
}
Beachten Sie, dass Sie die Deklaration von deadlineTime
als DispatchTime.now() + 1.0
schreiben können und das gleiche Ergebnis erhalten, da der +
Operator wie folgt überschrieben ist (ähnlich für -
):
func +(time: DispatchTime, seconds: Double) -> DispatchTime
func +(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime
Dies bedeutet, dass wenn Sie das DispatchTimeInterval
enum
nicht verwenden und einfach eine Zahl schreiben, angenommen wird, dass Sie Sekunden verwenden.
Swift 3+
Dies ist super einfach und elegant in Swift 3+:
DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) {
// ...
}
Ältere Antwort:
Um Cezarys Antwort zu erweitern, die nach 1 Nanosekunde ausgeführt wird, musste ich Folgendes tun, um nach 4,5 Sekunden auszuführen.
let delay = 4.5 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), block)
Bearbeitung: Ich habe festgestellt, dass mein originaler Code leicht falsch war. Implizites Typing führt zu einem Kompilierfehler, wenn Sie NSEC_PER_SEC nicht in ein Double konvertieren.
Wenn jemand eine optimale Lösung vorschlagen kann, wäre ich daran interessiert.
Matt's Syntax ist sehr gut und wenn Sie den Block ungültig machen müssen, möchten Sie vielleicht dies verwenden:
typealias dispatch_cancelable_closure = (cancel : Bool) -> Void
func delay(time:NSTimeInterval, closure:()->Void) -> dispatch_cancelable_closure? {
func dispatch_later(clsr:()->Void) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(time * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), clsr)
}
var closure:dispatch_block_t? = closure
var cancelableClosure:dispatch_cancelable_closure?
let delayedClosure:dispatch_cancelable_closure = { cancel in
if closure != nil {
if (cancel == false) {
dispatch_async(dispatch_get_main_queue(), closure!);
}
}
closure = nil
cancelableClosure = nil
}
cancelableClosure = delayedClosure
dispatch_later {
if let delayedClosure = cancelableClosure {
delayedClosure(cancel: false)
}
}
return cancelableClosure;
}
func cancel_delay(closure:dispatch_cancelable_closure?) {
if closure != nil {
closure!(cancel: true)
}
}
Verwendung wie folgt
let retVal = delay(2.0) {
println("Später")
}
delay(1.0) {
cancel_delay(retVal)
}
_Der Link oben scheint nicht zu funktionieren. Ursprünglicher Objc-Code von Github_
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.