Kann jemand erklären, was ist NSRunLoop
? Also, wie ich weiß, NSRunLoop
ist etwas mit NSThread
richtig verbunden? Nehmen wir also an, ich erstelle einen Thread wie
NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil];
[th start];
-(void) someMethod
{
NSLog(@"operation");
}
Also, nachdem dieser Thread seine Arbeit beendet hat, oder? Warum verwenden RunLoops
oder wo verwenden? Aus Apple-Dokumenten habe ich etwas gelesen, aber es ist mir nicht klar. Erklären Sie dies bitte so einfach wie möglich
ios
objective-c
cocoa-touch
nsrunloop
Taffarel
quelle
quelle
Antworten:
Eine Run-Schleife ist eine Abstraktion, die (unter anderem) einen Mechanismus zur Verarbeitung von Systemeingabequellen (Sockets, Ports, Dateien, Tastatur, Maus, Timer usw.) bietet.
Jeder NSThread verfügt über eine eigene Ausführungsschleife, auf die über die currentRunLoop-Methode zugegriffen werden kann.
Im Allgemeinen müssen Sie nicht direkt auf die Ausführungsschleife zugreifen, obwohl es einige (Netzwerk-) Komponenten gibt, mit denen Sie möglicherweise angeben können, welche Ausführungsschleife für die E / A-Verarbeitung verwendet wird.
Eine Ausführungsschleife für einen bestimmten Thread wartet, bis eine oder mehrere seiner Eingabequellen Daten oder Ereignisse enthalten, und löst dann die entsprechenden Eingabehandler aus, um jede Eingangsquelle zu verarbeiten, die "bereit" ist.
Danach kehrt es zu seiner Schleife zurück, verarbeitet Eingaben aus verschiedenen Quellen und "schläft", wenn keine Arbeit zu erledigen ist.
Das ist eine ziemlich allgemeine Beschreibung (versucht zu viele Details zu vermeiden).
BEARBEITEN
Ein Versuch, den Kommentar anzusprechen. Ich habe es in Stücke gebrochen.
Tatsächlich. NSRunLoop ist nicht threadsicher und sollte nur über den Kontext des Threads aufgerufen werden, in dem die Schleife ausgeführt wird.
Wenn Sie einen Port überwachen möchten, fügen Sie diesen Port einfach der Ausführungsschleife hinzu, und die Ausführungsschleife überwacht diesen Port auf Aktivität.
Sie können einen Timer auch explizit mit hinzufügen
Die Ausführungsschleife verarbeitet alle Bereitschaftsereignisse bei jeder Iteration (entsprechend ihrem Modus). Sie müssen sich die Dokumentation ansehen, um Informationen zu den Ausführungsmodi zu erhalten, da dies etwas über den Rahmen einer allgemeinen Antwort hinausgeht.
In den meisten Anwendungen wird die Hauptlaufschleife automatisch ausgeführt. Sie sind jedoch dafür verantwortlich, die Ausführungsschleife zu starten und auf eingehende Ereignisse für von Ihnen gesponnene Threads zu reagieren.
Ich bin mir nicht sicher, was du hier meinst. Sie fügen der Ausführungsschleife keine Ereignisse hinzu. Sie fügen Eingabequellen und Timerquellen hinzu (aus dem Thread, dem die Ausführungsschleife gehört). Die Run-Schleife überwacht sie dann auf Aktivität. Sie können natürlich Daten von anderen Threads und Prozessen bereitstellen, aber die Eingabe wird von der Ausführungsschleife verarbeitet, die diese Quellen in dem Thread überwacht, in dem die Ausführungsschleife ausgeführt wird.
Tatsächlich. Tatsächlich "bleibt" eine Ausführungsschleife in einem Ereignishandler, bis dieser Ereignishandler zurückgekehrt ist. Sie können dies in jeder App einfach genug sehen. Installieren Sie einen Handler für jede E / A-Aktion (z. B. Tastendruck), die sich im Ruhezustand befindet. Sie blockieren die Hauptlaufschleife (und die gesamte Benutzeroberfläche), bis diese Methode abgeschlossen ist.
Gleiches gilt für jede Run-Schleife.
Ich schlage vor, Sie lesen die folgende Dokumentation zu Run-Loops:
https://developer.apple.com/documentation/foundation/nsrunloop
und wie sie in Threads verwendet werden:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1
quelle
performSelector:onThread:withObject:waitUntilDone:
, übergeben Sie einNSThread
Objekt, und Ihre Auswahl wird im Runloop dieses Threads geplant.Sie ermöglichen es Ihnen, zu warten, bis der Benutzer tippt und entsprechend reagiert, zu warten, bis Sie einen CompletionHandler erhalten, und seine Ergebnisse anzuwenden, zu warten, bis Sie einen Timer erhalten, und eine Funktion auszuführen. Wenn Sie keinen Runloop haben, können Sie nicht auf Benutzertipps warten / warten, Sie können nicht warten, bis ein Netzwerkanruf stattfindet, Sie können nicht in x Minuten geweckt werden, es sei denn, Sie verwenden
DispatchSourceTimer
oderDispatchWorkItem
Auch aus diesem Kommentar :
Speziell zu: "Hintergrund-Threads haben keine eigenen Runloops". Der folgende Timer kann bei einem asynchronen Versand nicht ausgelöst werden :
Ich denke, der Grund, warum der
sync
Block auch ausgeführt wird, ist folgender:Sync - Blöcke in der Regel nur innerhalb ihrer ausgeführt werden soll Quelle Warteschlange. In diesem Beispiel ist die Quellwarteschlange die Hauptwarteschlange, die beliebige Warteschlange die Zielwarteschlange.
Um zu testen, dass ich mich bei
RunLoop.current
jedem Versand angemeldet habe .Der Synchronisierungsversand hatte dieselbe Runloop wie die Hauptwarteschlange. Während der RunLoop innerhalb des asynchronen Blocks eine andere Instanz als die anderen war. Sie überlegen sich vielleicht, warum
RunLoop.current
ein anderer Wert zurückgegeben wird. Ist es nicht ein gemeinsamer Wert? Gute Frage! Lesen Sie weiter:WICHTIGE NOTIZ:
Die class -Eigenschaft
current
ist KEINE globale Variable.Es ist kontextbezogen. Es ist nur im Rahmen des Threads sichtbar, dh im Thread-lokalen Speicher . Mehr dazu hier .
Dies ist ein bekanntes Problem bei Timern. Sie haben nicht das gleiche Problem, wenn Sie verwenden
DispatchSourceTimer
quelle
RunLoops sind ein bisschen wie eine Box, in der einfach etwas passiert.
Grundsätzlich verarbeiten Sie in einer RunLoop einige Ereignisse und kehren dann zurück. Oder kehren Sie zurück, wenn keine Ereignisse verarbeitet werden, bevor das Timeout erreicht ist. Sie können sagen, dass es asynchronen NSURLConnections ähnelt. Sie verarbeiten Daten im Hintergrund, ohne Ihre aktuelle Schleife zu stören, und gleichzeitig benötigen Sie Daten synchron. Dies kann mit Hilfe von RunLoop erfolgen, das Sie asynchron macht
NSURLConnection
und Daten zum Zeitpunkt des Aufrufs bereitstellt. Sie können einen RunLoop wie folgt verwenden:In dieser RunLoop wird sie ausgeführt, bis Sie einige Ihrer anderen Arbeiten abgeschlossen und YourBoolFlag auf false gesetzt haben .
Ebenso können Sie sie in Threads verwenden.
Hoffe das hilft dir.
quelle
Von hier
Von hier
quelle