Richtige Handhabung / Aufräumen / etc CADisplayLink im Swift-benutzerdefinierte animation?
Betrachten Sie dieses trivial-sync-animation mit CADisplayLink
,
var link:CADisplayLink?
var startTime:Double = 0.0
let animTime:Double = 0.2
let animMaxVal:CGFloat = 0.4
private func yourAnim()
{
if ( link != nil )
{
link!.paused = true
//A:
link!.removeFromRunLoop(
NSRunLoop.mainRunLoop(), forMode:NSDefaultRunLoopMode)
link = nil
}
link = CADisplayLink(target: self, selector: #selector(doorStep) )
startTime = CACurrentMediaTime()
link!.addToRunLoop(
NSRunLoop.currentRunLoop(), forMode:NSDefaultRunLoopMode)
}
func doorStep()
{
let elapsed = CACurrentMediaTime() - startTime
var ping = elapsed
if (elapsed > (animTime / 2.0)) {ping = animTime - elapsed}
let frac = ping / (animTime / 2.0)
yourAnimFunction(CGFloat(frac) * animMaxVal)
if (elapsed > animTime)
{
//B:
link!.paused = true
link!.removeFromRunLoop(
NSRunLoop.mainRunLoop(), forMode:NSDefaultRunLoopMode)
link = nil
yourAnimFunction(0.0)
}
}
func killAnimation()
{
//for example if the cell disappears or is reused
//C:
????!!!!
}
Scheint es verschiedene Probleme.
Unter (A:), obwohl link
ist nicht null, kann es nicht möglich sein, entfernen Sie es von einer Schlinge. (Zum Beispiel, die jemand haben kann, initialisiert es mit link = link:CADisplayLink()
- probieren Sie es für einen crash.)
Zweitens auf (B:) es scheint ein Durcheinander ... sicherlich gibt es bessere (und mehr Swift) Weg, und was ist, wenn es null-auch wenn die Zeit gerade abgelaufen ist?
Schließlich in (C:) wenn Sie wollen, brechen die anim ... habe ich depressiv und habe keine Ahnung was am besten ist.
Und wirklich den code auf A: und B: sollte das gleiche call-Recht, eine Art clean-up-call.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ein einfaches Beispiel zeigen, wie ich gehen über die Implementierung eines
CADisplayLink
(im Swift-3):Punkte zu beachten:
nil
hier zu vertreten, der Staat, in dem die display-link nicht ausgeführt wird – denn es gibt keinen einfachen Weg, um diese Informationen aus einer ungültig display link.removeFromRunLoop()
verwenden wirinvalidate()
, die nicht Abstürzen, wenn die Anzeige link nicht bereits Hinzugefügt wurden, um eine run-loop. Doch diese situation sollte nicht auftreten, in Erster Linie – da sind wir immer sofort das hinzufügen der Anzeige von link auf dem run-Schleife nach der Erstellung.displayLink
privaten, um zu verhindern, dass außerhalb von Klassen aus, dass es in einem unerwarteten Zustand (e.g ungültig, aber nicht die Einstellungnil
).stopDisplayLink()
Methode, die sowohl erlischt die Anzeige link (wenn er ungleich null) und setztnil
– anstatt das kopieren und einfügen dieser Logik.paused
zutrue
vor der Aufhebung der Anzeige-link, da dieser redundant ist.displayLink
nach Prüfung für nicht-null verwenden wir optional chaining-e.gdisplayLink?.invalidate()
(aufgerufeninvalidate()
wenn die Anzeige link nicht null). Während Kraft, Ausgliedern kann "sicher" in Ihrer gegebenen situation (wie Sie überprüft haben, für null) – es ist potentiell unsicher, wenn es um die zukünftige Umgestaltung, wie Sie können re-strukturieren Sie Ihre Logik, ohne zu berücksichtigen, welche Auswirkungen dies auf die Kraft packt.elapsed
Zeit, um die animation Dauer, um sicherzustellen, dass die spätere animation Logik produziert nicht einen Wert außerhalb des erwarteten Bereichs.displayLinkDidFire(_:)
übernimmt ein einzelnes argument des TypsCADisplayLink
Bedarf durch die Dokumentation.displayLink?.invalidate()
.......... nicht, dass lassen Sie es "in" ein runloop ?!?! (auch wenn ungültig???)invalidate()
entfernt die angegebene display-link von allen run-loop-Modi, die wiederum bewirkt, dass es zu sein veröffentlicht von der run-Schleife.Erkenne ich diese Frage bereits eine gute Antwort, aber hier ist noch ein etwas anderer Ansatz, der hilft, in der Umsetzung glatte Animationen unabhängig von der display-link-frame-rate.
**(Link zu demo-Projekt-zur Verfügung an der Unterseite dieser Antwort - UPDATE: demo-Projekt source-code wird nun aktualisiert, um Swift 4)
Für meine Umsetzung habe ich entschieden, wickeln Sie die display-link-in seiner eigenen Klasse und setup eine delegate-Referenz zu bekommen, die mit der delta-Zeit (die Zeit zwischen der letzten Anzeige link aufrufen und den aktuellen call) so führen wir unsere Animationen ein wenig mehr reibungslos.
Ich bin derzeit mit dieser Methode zu animieren ~60-Ansichten auf dem Bildschirm gleichzeitig in einem Spiel.
Ersten wir definieren die delegate-Protokoll, dass unser wrapper aufrufen, wird eine Benachrichtigung über update-Ereignisse.
Weiter, wir definieren unsere display-link-wrapper-Klasse. Diese Klasse nehmen Sie einen Delegaten Verweis auf die Initialisierung. Wenn die Initialisierung wird automatisch gestartet, display-link, und reinigen Sie es bis auf deinit.
Es zu benutzen Sie einfach die Initialisierung einer Instanz der wrapper, vorbei an der Delegierten-listener Verweis, dann aktualisieren Sie Ihre Animationen auf der Grundlage der delta-Zeit. In diesem Beispiel wird der Stellvertretung geht der Aufruf von update aus, um die animiert anzeigen (auf diese Weise konnten Sie verfolgen, mehrere animieren Blick haben und jedes update Ihre Positionen über diesen Anruf).
Beweglichen Ansichten update-Funktion sieht wie folgt aus:
Wenn Sie möchten, sich durch ein komplettes demo-Projekt, Sie können es von GitHub hier: CADisplayLink Demo-Projekt
Oben ist das beste Beispiel, wie CADisplayLink mit Effizienz. Dank @Fattie und @digitalHound
Ich konnte nicht widerstehen, hinzufügen von meine Verwendung von CADisplayLink und DisplayUpdater Klassen von 'digitalHound' im PdfViewer mit WKWebView.
Meine Anforderung war weiterhin auto-scroll-pdf an den Anwender wählbare Geschwindigkeit.
Kann die Antwort hier ist nicht der richtige Ort, aber ich habe die Absicht zu zeigen, die Verwendung von CADisplayLink hier. ( für andere, wie ich, die Umsetzung Ihrer Anforderung. )
Beispiel der Aufruf aus einer anderen Sicht als unter.
Laden Sie die PDF-Datei von Dokument-Ordner.
Diesem Beispiel kann 'modified' zu laden web-Seite und auto-scrollen Sie auf Benutzer ausgewählten Geschwindigkeit.
Hinsichtlich
Sanjay.