Während eine UIScrollView
(oder eine abgeleitete Klasse davon) scrollt, scheint es wie alleNSTimers
ausgeführten Dateien angehalten, bis der ist.
Gibt es eine Möglichkeit, dies zu umgehen? Themen? Eine Prioritätseinstellung? Etwas?
ios
uiscrollview
nstimer
mcccclean
quelle
quelle
Antworten:
Eine einfach zu implementierende Lösung ist:
quelle
Für alle, die Swift 3 verwenden
quelle
timer = Timer(timeInterval: 0.1, target: self, selector: aSelector, userInfo: nil, repeats: true)
als erster Befehl statt als aufzurufenTimer.scheduleTimer()
, dascheduleTimer()
der Runloop mit einem Timer versehen wird und der nächste Aufruf ein weiterer Befehl zum gleichen Runloop ist, jedoch mit einem anderen Modus. Mach nicht zweimal die gleiche Arbeit.Ja, Paul hat recht, dies ist ein Run-Loop-Problem. Insbesondere müssen Sie die NSRunLoop-Methode verwenden:
quelle
Dies ist die schnelle Version.
quelle
Sie müssen einen anderen Thread und eine weitere Ausführungsschleife ausführen, wenn Timer beim Scrollen ausgelöst werden sollen. Da Timer als Teil der Ereignisschleife verarbeitet werden, gelangen Sie nie zu den Timern, wenn Sie mit dem Scrollen Ihrer Ansicht beschäftigt sind. Obwohl die Perf / Batterie-Strafe für das Ausführen von Timern auf anderen Threads in diesem Fall möglicherweise nicht sinnvoll ist.
quelle
Verwenden Sie für alle Swift 4:
quelle
tl; dr Der Runloop führt einen Bildlauf durch, sodass keine Ereignisse mehr verarbeitet werden können - es sei denn, Sie stellen den Timer manuell so ein, dass dies auch passieren kann, wenn der Runloop Berührungsereignisse verarbeitet. Oder versuchen Sie es mit einer alternativen Lösung und verwenden Sie GCD
Ein Muss für jeden iOS-Entwickler. Viele Dinge werden letztendlich über RunLoop ausgeführt.
Abgeleitet von Apples Dokumenten .
Was ist eine Run-Schleife?
Wie wird die Zustellung von Ereignissen gestört?
Was passiert, wenn der Timer ausgelöst wird, während sich die Ausführungsschleife mitten in der Ausführung befindet?
Dies geschieht VIELE MAL, ohne dass wir es jemals bemerken. Ich meine, wir setzen den Timer auf 10: 10: 10: 00, aber der Runloop führt ein Ereignis aus, das bis 10: 10: 10: 05 dauert, daher wird der Timer 10: 10: 10: 06 ausgelöst
Würde sich das Scrollen oder irgendetwas, das den Runloop beschäftigt, ständig verschieben, wenn mein Timer ausgelöst wird?
Wie kann ich den RunLoops-Modus ändern?
Das kannst du nicht. Das Betriebssystem ändert sich nur für Sie. Wenn der Benutzer z. B. tippt, wechselt der Modus zu
eventTracking
. Wenn die Benutzertipps beendet sind, kehrt der Modus zurück zudefault
. Wenn Sie möchten, dass etwas in einem bestimmten Modus ausgeführt wird, müssen Sie sicherstellen, dass dies geschieht.Lösung:
Wenn der Benutzer einen Bildlauf durchführt, wird der Run-Loop-Modus aktiviert
tracking
. Der RunLoop ist zum Schalten ausgelegt. Sobald der Modus eingestellt isteventTracking
, gibt es Priorität (denken Sie daran, dass wir nur begrenzte CPU-Kerne haben), um Ereignisse zu berühren. Dies ist ein architektonischer Entwurf der OS-Designer .Standardmäßig sind Timer NICHT für den
tracking
Modus geplant. Sie sind geplant am:Das
scheduledTimer
Folgende macht das:Wenn Sie möchten, dass Ihr Timer beim Scrollen funktioniert, müssen Sie Folgendes tun:
Oder einfach:
Wenn Sie einen der oben genannten Schritte ausführen, wird Ihr Thread nicht durch Berührungsereignisse blockiert. was äquivalent ist zu:
Alternative Lösung:
Sie können GCD für Ihren Timer verwenden, um Ihren Code vor Problemen mit der Verwaltung von Ausführungsschleifen zu schützen.
Für nicht wiederholte verwenden Sie einfach:
Verwenden Sie zum Wiederholen von Timern:
Erfahren Sie, wie Sie DispatchSourceTimer verwenden
Aus einer Diskussion mit Daniel Jalkut vertiefen:
Frage: Wie wird GCD (Hintergrundthreads), z. B. ein asynchroner After in einem Hintergrundthread, außerhalb von RunLoop ausgeführt? Mein Verständnis davon ist, dass alles innerhalb einer RunLoop ausgeführt werden soll
Nicht unbedingt - jeder Thread hat höchstens eine Ausführungsschleife, kann aber Null haben, wenn es keinen Grund gibt, die Ausführung "Besitz" des Threads zu koordinieren.
Threads sind ein Vorteil auf Betriebssystemebene, mit dem Ihr Prozess seine Funktionalität auf mehrere parallele Ausführungskontexte aufteilen kann. Ausführungsschleifen sind eine Möglichkeit auf Framework-Ebene, mit der Sie einen einzelnen Thread weiter aufteilen können, damit er von mehreren Codepfaden effizient gemeinsam genutzt werden kann.
Wenn Sie etwas versenden, das in einem Thread ausgeführt wird, hat es normalerweise keinen Runloop, es sei denn, es wird etwas aufgerufen,
[NSRunLoop currentRunLoop]
das implizit einen erstellen würde.Kurz gesagt, Modi sind im Grunde genommen ein Filtermechanismus für Eingänge und Timer
quelle