Tags: Apple Ted Def Mes Objekt Klasse Ble Basis Anruf hinzufügen
Ich weiß nicht, ob Sie haben jemals darüber nachgedacht, dieses Problem eine app beginnt nach die Ausführung dort platziert wird, geht man davon aus, dass es für jede Aktion nicht zutrifft. Die app ist so zart wie es ist, und es gibt keine spontane Aktion, der sowieso. Aber angenommen, wir klicken Sie auf einen Button auf der Oberfläche. An dieser Stelle werden ein entsprechende Antwort-Ereignis der Schaltfläche. Es fühlt sich an wie die app ständig im Standby-Modus gewesen ist. Es hat geruht, wenn niemand arbeitet, und es sofort reagieren kann, wenn es erlaubt ist, zu arbeiten. In der Tat ist dies der Kredit laufen Schleife.
Erste, Fäden und laufen Schleife
1.1 Arten von Thread-Aufgaben
Wieder Fäden. Einige Threads Aufgaben, die einer geraden Linie, ausgehend vom Anfang bis zum Ende, während andere, die die Arbeit machen einen Kreis. Schleifen Sie halten Sie, bis sie in irgendeiner Weise beendet wird.
Lineare Themen, wie z. B. einfache Hello World, beenden drucken und ihres Lebenszyklus ist beendet. Wie ein Strohfeuer; führt eine kreisförmige Art, wie ein Betriebssystem bis Sie heruntergefahren. In IOS sind Runde Fäden durch eine Nonstop-Schleife laufen Schleife implementiert.
1.2 die Beziehung zwischen Threads und laufen Schleife
Führen Schleife, wie der Name andeutet, repräsentiert Schleife eine Schleife, die zusammen laufen, mit eine Schleife darstellt, die ausgeführt wurde. In der Tat laufen Schleife und Gewinde sind eng verbunden, so zu sprechen, laufen Schleife wird für Thread geboren und hat keine Threads. Es gibt keine Notwendigkeit dafür vorhanden sein. Führen Sie Schleifen ist die Infrastruktur Teil des Gewindes und Kakao und CoreFundation bieten das laufen Schleife-Objekt, das ist einfach zu konfigurieren und Verwalten von Threads (nachfolgend finden Sie Beispiele für Kakao).
Jeder Thread. Der Haupt-Thread mit dem Programm (Haupt-Thread) hat das entsprechende Objekt ausführen Schleife.
Die geführten Schleife für die 1.2.1 Hauptthread wird standardmäßig gestartet.
IOS-app, nachdem das Programm gestartet wurde, wird eine Funktion main () wie folgt:
int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([appDelegate class])); } }
Der Schwerpunkt liegt auf der UIApplicationMain () Funktion, die ein NSRunLoop-Objekt für Haupt-Thread, legt, was erklärt fest, warum unsere app ausruhen kann, wenn niemand ist in Betrieb und muss in der Lage, sofort reagieren, wenn es funktioniert.
1.3 einige Anweisungen ausführen Schleife
Die NSRunLoop-Klasse in 1.3.1 Kakao ist nicht Thread-sicher
Wir können nicht mehr laufen Schleife Objekt von einem anderen Thread in einem Thread manipulieren. Das wäre sehr wahrscheinlich haben unbeabsichtigte Konsequenzen.
Glücklicherweise die undurchsichtige Klasse CFRunLoopRef in der CoreFundation ist Thread-sicher, und die zwei Arten von geführten Schleife sind voll gemischt, um zu verwenden. Die NSRunLoop-Klasse in Kakao kann eine Instanzmethode verdeutlicht werden:
- (CFRunLoopRef) GetCFRunLoop;
Ruft die entsprechende CFRunLoopRef-Klasse. Thread-sichere Zwecke zu erreichen.
Die Verwaltung der 1.3.2 betrieben Schleife wird nicht ganz auf eigene Initiative.
Wir haben noch design-Thread-Code zum Starten geführte Schleife zum richtigen Zeitpunkt und richtig reagieren, um Eingabeereignisse, vorausgesetzt natürlich, die lief, Schleife im Thread erforderlich ist. Wir müssen auch, verwenden Sie die WHILE/Anweisung auf Laufwerk ausführen Schleife zum Schleifen ausführen. Der folgende Code fährt erfolgreich geführte Schleife:
BOOL isRunning = NO; do { isRunning = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDatedistantFuture]]; } while (isRunning);
1.3.3 Run Schleife ist auch verantwortlich für die Erstellung und Veröffentlichung von stiges Pool zur gleichen Zeit
In Projekten, die manuelle Speicherverwaltung verwenden, sind eine sehr große Anzahl von Objekten, die auf eigene Faust aktiv freigegeben werden oft verwendet, geht man davon aus, dass diese Objekte können nicht sofort freigegeben werden, was zu einem starken Anstieg der Speicherbedarf. Laufen Sie, Schleife tut dies für uns, und wenn eine Ausführungsschleife endet, es löst den stiges Pool, und alle Variablen vom Typ eine eigene aktive Version im Pool werden zur gleichen Zeit freigegeben.
Die Stärken der 1.3.4 führen Schleife
Eine geführte Schleife ist eine Ereignisbehandlung Schleife, die zur kontinuierlichen Überwachung und Eingabeereignisse zu verarbeiten und weisen sie auf entsprechende Ziele für die Verarbeitung verwendet wird. Geht man davon aus, dass Sie nur dieses Feature implementieren möchten, könnten Sie denken, dass eine einfache while-Schleife wird nicht funktionieren, und Sie in der Lage werden, einen komplizierten Mechanismus mit dem Aufwand des Chefs zu tun? Natürlich Apples Architekten nicht getrockneten Essen, und sie haben lange darüber nachgedacht.
Vor allem NSRunLoop ist ein anspruchsvoller Nachricht Verarbeitungsmodus, er ist brillant in der Message-Verarbeitung Prozess zur besseren Abstraktion und Kapselung, so dass Sie keinen Umgang mit einigen sehr trivial sehr Low-Level-detaillierte Nachricht verarbeiten, in NSRunLoop, die jede Nachricht in der Eingabe verpackt wird Quelle oder Timer beziehen (siehe Artikel unten).
Zweitens ist es auch ein sehr wichtiger Punkt. Mit Run Schleife ermöglicht Ihre Fäden um zu arbeiten, wenn sie einen Job haben und Ruhezustand, wenn sie nicht arbeiten können die Systemressourcen stark sparen.
Zweite, geführtes Schleife im Zusammenhang Wissenspunkte
2.1 Eingabeereignis Quelle
Führen Sie Schleife erhält Eingabeereignisse aus zwei verschiedenen Quellen: Eingang Quelle und Timing-Quelle (Timer Quellen). Beide Quellen verwenden eine besondere Verarbeitung Routine des Programms, um die Ereignisse zu verarbeiten, die ankommen. Abbildung 1 zeigt die konzeptionelle Struktur der geführten Schleife und verschiedenen Quellen.
Was gesagt werden muss ist. Beim Erstellen einer Eingangsquelle. Sie müssen eine oder mehrere Modi in laufen Schleife (was ist das Muster, wie unten beschrieben) zuweisen. Muster gelten nur für die Quelle in ein bestimmtes Ereignis zu hören.
In den meisten Fällen führt laufen Schleife in Verzug Modus. Aber Sie können auch in Ihrem eigenen definierten Modus ausführen. Wenn eine Quelle nicht im aktuellen Modus überwacht wird, ist die generierte Nachricht übergeben, nur dann, wenn die Laufe Schleife in seinem damit verbundenen Modus ausgeführt wird.
Geben Sie Abbildung 1 Runloop Struktur und Eingangsquelle
2.1.1 Eingangsquelle
Vorbei an asynchrone Ereignisse, Nachrichten in der Regel aus anderen Threads oder Programme. Die Eingabequelle übergibt eine asynchrone Meldung an die entsprechende Verarbeitung Routine und ruft die RunUntilDate: Methode (den zugehörigen NSRunLoop Objekt Anruf im Gewinde) zu beenden.
2.1.1.1 Port basierte Eingangsquelle
Portbasierte input-Quellen sind auf eigene Faust durch den Kernel geschickt.
Kakao und der Kern-Stiftung haben integrierte portbasierte Quellen, die die Verwendung von Port-bezogene Objekte und Funktionen unterstützen.
Zum Beispiel in Kakao müssen Sie nie eine Eingangsquelle direkt erstellen. Sie einfach ein Portobjekt erstellen und verwenden Sie die NSPort-Methode hinzufügen den Hafen um die Schleife ausgeführt. Die Port-Objekt übernimmt die Erstellung und Konfiguration von Eingabequellen auf eigene.
An der Kern-Stiftung müssen Sie manuell erstellen, Hafen und seinen Lauf Schleife Quelle. Wir sind in der Lage, verwenden Sie Port-bezogene Funktionen (Cfmachportref, Cfmessageportref. CFSocketRef), das richtige Objekt zu erstellen.
Das folgende Beispiel veranschaulicht eine portbasierte Eingangsquelle zu erstellen, fügen Sie es um Schleife führen, und starten:
voidcreatePortSource(){ CFMessagePortRef port = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("com.someport"),myCallbackFunc, NULL, NULL); CFRunLoopSourceRef source = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, port, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); while (pageStillLoading) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; CFRunLoopRun(); [pool release]; } CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); CFRelease(source);}
2.1.1.2 die Eingangsquelle selbst definieren
Die Eingabequelle Ihrer eigenen Definition muss manuell aus einem anderen Thread gesendet werden.
Um eigene definierte Eingangsquelle zu erstellen, müssen Sie eine Funktion in Bezug auf die CFRunLoopSourceRef Art innerhalb der Kern-Stiftung verwenden, um es zu schaffen.
Die Callback-Funktion können Sie um Ihre eigene definierte Eingangsquelle zu konfigurieren. Kern-Fundation ruft Callback-Funktionen in den verschiedenen Teilen der Konfigurationsquelle Eingabeereignisse zu behandeln. Wenn die Quelle von Run Schleife entfernt wird aufräumen.
Neben der Definition des Verhaltens der Eingangsquelle selbst definieren, wenn das Ereignis eintrifft, müssen Sie auch die Messaging-Mechanismus definieren. Dieser Teil der Quelle wird in einem separaten Thread ausgeführt. Und ist verantwortlich für die Übergabe von Daten an der Quelle und benachrichtigen sie, die Daten zu verarbeiten, während die Daten darauf wartet, verarbeitet werden. Die Definition des Messaging-Mechanismus hängt von Ihnen ab. Aber es ist am besten nicht zu kompliziert zu sein. Erstellen Sie und starten Sie Ihre eigene Definition von die Eingangsquelle, wie unten dargestellt:
voidcreateCustomSource(){ CFRunLoopSourceContext context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); while (pageStillLoading) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; CFRunLoopRun(); [pool release]; } CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); CFRelease(source);}
Selektor-Quelle auf 2.1.1.3Cocoa
Neben Port-basierte Quellen. Kakao die Eingabequelle ihrer eigenen Definition definiert und erklärt sich damit einverstanden, dass Sie die Selector-Methode auf einem beliebigen Thread ausgeführt. Identisch mit der Port-basierten Quellen. Erledigung eines Ersuchens der Selektor wird auf dem Zielthread serialisiert. Verlangsamen Sie viele Synchronisationsprobleme auf dem Thread, die mehrere Methode einfach zustimmen.
Nicht wie eine portbasierte Quelle. Wenn ein Selektor ausgeführt wird, wird er oder sie die Initiative von der geführten Schleife zu entfernen nehmen.
Wenn Selektor auf andere Threads ausgeführt wird, muss die Ziel-Thread eine aktivere laufen Schleife enthalten. Für den Thread, den Sie erstellt. Dies bedeutet, dass der Thread nicht die Selector-Methode ausgeführt werden, bis Sie explizit ausführen Schleife beginnen. Aber ruhend aller Zeiten wurde.
Die neutralen-Klasse stellt ähnliche Selektor-Methoden, wie z. B. die folgenden:
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)argwaitUntilDone:(BOOL)wait modes:(NSArray *)array;
2.1.2 Timing-Quelle (Timer-Quelle)
Timing-Quellen übergeben Nachrichten synchron zu einem voreingestellten Zeitpunkt rechtzeitig. Alle diese Nachrichten auftreten, zu einem bestimmten Zeitpunkt oder in wiederholten Abständen. Die Timing-Quelle übergibt die Nachricht direkt an die Verarbeitung Routine und wird nicht sofort ausführen Schleife beendet.
Es wird darauf hingewiesen, dass während der Timer zeitbasierte Benachrichtigungen erzeugen kann, es kein Echtzeit-Mechanismus ist. Wie bei der Eingangsquelle, bezieht sich der Timer auch auf das spezifische Muster Ihrer geführten Schleife.
Geht man davon aus, dass der Modus, in dem der Timer wohnt, derzeit nicht von geführten Schleife überwacht wird, startet der Timer nicht bis in den entsprechenden Modus laufen Schleife ausführt. Ebenso wird davon ausgegangen, dass der Timer während der geführten Schleifenverarbeitung eines Ereignisses beginnt. Der Timer wartet, bis die nächste Laufe Schleife mit der entsprechenden Handler beginnt.
Unter der Annahme, dass laufen, dass die Schleife nicht mehr ausgeführt wird, wird der Timer nicht gestartet.
Es gibt zwei Möglichkeiten, eine Timer-Quelle zu erstellen.
Methode I: Datumswechsel * Timer = [Datumswechsel ScheduledTimerWithTimeInterval:4.0 Targe T:Self-Selektor: @selector (Backgroundthreadfire:) UserInfo:nil Wiederholungen: Ja]; [[NSRunLoop CurrentRunLoop] AddTimer:timerforMode:NSDefaultRunLoopMode]; Methode II: [Datumswechsel ScheduledTimerWithTimeInterval:10 Ziel: selbst Selektor: @selector (Backgroundthreadfire:) UserInfo:nil Wiederholungen: Ja];
2.2 RunLoop Beobachter
Die Quelle wird ausgelöst, wenn das entsprechende synchrone oder asynchrone Ereignis auftritt, und laufen Loop Beobachter, zu einem bestimmten Zeitpunkt ausgelöst wird, wann die laufen Schleife selbst ausführt.
Führen Sie Loop Beobachter können Sie bereiten für ein bestimmtes Ereignis oder einen Thread, der in den Ruhezustand geht.
Sie können die folgenden Ereignisse laufen Schleife Beobachter zuordnen:
1. Runloop Eingang
2. wann Runloop kümmert sich einen timer
3. wann Runloop kümmert sich eine Eingangsquelle
4. wann Runloop wechselt in den Ruhezustand
5. wann Runloop erwacht ist, aber die Ereignisse, die vor dem Erwachen behandelt werden
6. Runloop Kündigung
Ähnlich wie der Timer zum Zeitpunkt der Erstellung können Sie angeben, dass es laufen Schleife Beobachter nur einmal oder in einer Schleife verwenden kann. Wenn Sie es nur einmal verwenden. So, nachdem es beginnt. Entzieht sich der geführten Schleife während der Beobachter für die Schleife nicht. Definieren Sie den Betrachter und fügen Sie hinzu, um die Schleife ausgeführt. Sie können nur Kern Fundation.
Das folgende Beispiel zeigt wie erstelle ich einen Beobachter für Run-Schleife:
- (void)addObserverToCurrentRunloop{ // The application uses garbage collection, so noautorelease pool is needed. NSRunLoop*myRunLoop = [NSRunLoop currentRunLoop]; // Create a run loop observer and attach it to the runloop. CFRunLoopObserverContext context = {0, self, NULL, NULL, NULL}; CFRunLoopObserverRef observer =CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeTimers, YES, 0, &myRunLoopObserver, &context); if (observer) { CFRunLoopRef cfLoop = [myRunLoop getCFRunLoop]; CFRunLoopAddObserver(cfLoop, observer, kCFRunLoopDefaultMode); }}
von KCFRunLoopBeforeTimers weist darauf hin, dass die Listener-Timer aktiviert ist, um das Pre-processing Ereignis auszulösen. Die folgende Ja zeigt kreisförmige hören.
Event-Warteschlangen für 2,3 RunLoop
Führen Sie ausführen Schleife jedes Mal aus. Deinen Thread laufen Schleife paar ergreifen die Initiative zuvor unbehandelte Nachrichten verarbeiten und die entsprechenden Beobachter benachrichtigen. Detaillierten Auftrag wie folgt:
Benachrichtigen Sie den Betrachter, die ausgeführt werden, dass Schleife gestartet wurde
Benachrichtigen Sie den Betrachter, egal was die den Timer zu starten,
Benachrichtigen Sie den Betrachter, die egal was steht in den Startlöchern, der Port-basierte Quelle
Starten Sie eine Port-basierte Quelle, egal, was bereit ist.
Davon ausgehen Sie, dass die Port-basierte Quelle bereit ist und im Wartezustand, sofort starten Sie, und gehen Sie zu Schritt 9.
Benachrichtigt die Beobachter, dass der Thread den Ruhezustand Eintritt
Tritt das Ereignis, das den Thread ruhenden bis eines der folgenden Orte:
Ein Ereignis kommt an einen Port-basierte Quelle
Timer-Start
Die Zeit von Run-Schleife ist abgelaufen
Laufen-Schleife wird explizit geweckt
Benachrichtigt dem Beobachter, dass der Thread geweckt werden.
Umgang mit unbehandelte Veranstaltungen
Davon ausgehen Sie, dass die benutzerdefinierte Timer beginnt, das Timer-Ereignis behandelt und ausführen Schleife Neustart.
Gehen Sie zu Schritt 2
Angenommen Sie, die Eingangsquelle beginnt und führt die entsprechende Nachricht
Nehmen Sie an geführten Schleife wird explizit geweckt und die Zeit hat nicht das Zeitlimit laufen Schleife neu starten. Gehen Sie zu Schritt 2
Benachrichtigt die Beobachter, die Enden der Schleife ausgeführt.
Da der Timer und der Beobachter für die Eingangsquelle die Nachricht übermitteln, bevor das entsprechende Ereignis eintritt, möglicherweise ein Fehler zwischen dem Zeitpunkt der Benachrichtigung und der Zeitpunkt des Auftretens die eigentliche Veranstaltung. Es wird angenommen, dass präzise Kontrolle erforderlich ist. Können Sie den Ruhezustand und Weck-Benachrichtigungen unterstützen Sie Korrektur gelesen, wenn ein Ereignis tatsächlich eintritt.
Da Timer und andere wiederkehrende Ereignisse müssen oft übergeben werden, wenn Sie laufen Schleife ausführen, Rückgängigmachen laufen wird Schleife beendet auch messaging.
Ein typisches Beispiel ist die Maus Weg verfolgen.
Da Code die Nachricht direkt, anstatt es durch das Programm erhält, startet der aktiven Timer nicht, bis die Maus Verfolgung abgeschlossen ist und die Steuerung wird an das Programm übergeben.
Laufen-Schleife kann explizit durch das laufen Schleife Objekt geweckt werden. Andere Meldungen können auch geführte Schleife aufwachen.
Z. B. hinzufügen einen neuen Port-basierte Quelle wacht laufen Schleife so, dass die Eingangsquelle sofort verarbeitet werden kann, ohne auf andere Ereignisse vor der Verarbeitung warten.
Wie Sie aus diesem Ereignis-Queue sehen können:
① wird davon ausgegangen, dass das Ereignis eintrifft und, dass die Nachricht an den entsprechenden Handler zur Verarbeitung übergeben wird, Runloop laufen Schleife beendet, nachdem das zweite Ereignis verarbeitet wird. Und egal ob die vorherigen geplant ist nun die Zeit gekommen. Sie können laufen Schleife wieder zu warten, bis das nächste Event starten.
② wird davon ausgegangen, dass es Quellen in dem Thread, die verarbeitet werden müssen, aber wenn das entsprechende Ereignis nicht ankommt, wird der Thread überwintern und warten Sie auf das entsprechende Ereignis eintritt. Das ist warum laufen ist Schleife so anstrengenden Arbeitstag, wenn Threads einen Job haben. Und ist inaktiv, wenn Sie nicht arbeiten.
2.4 Wann man Run-Schleife verwenden
Nur müssen Sie explizit eine laufen Schleife ausführen, wenn Sie einen Worker-Thread für Ihr Programm erstellen. Laufen Loop ist ein zentraler Bestandteil des Programms Hauptthread Infrastruktur. Daher bieten die Kakao und Carbon-Programme eine Schleife für den Code, um das Hauptprogramm ausführen und die geführte Schleife auf eigene Initiative zu initiieren. Die Run-Methode in der IOS-Programm (oder NSApplication in Mac OS X) ist UIApplication im Rahmen des Startup Programmschritt, der die Hauptschleife des Programms beginnt, wenn das Programm normal startet. Ähnlich. Die RunApplicationEventLoop-Funktion startet die Hauptschleife des Carbon-Programms. Angenommen, Sie eine Vorlage zur Verfügung gestellt von Xcode verwenden, um Ihr Programm zu erstellen, haben Sie nie explizit diese Routinen selbst aufrufen.
Für die Worker-Threads. Du musst ableiten, ob eine geführte Schleife ein muss ist. Annahmen sind notwendig. Dann müssen Sie es selbst konfigurieren und starten Sie ihn.
Du musst eine geführte Fadenschlinge unter keinen Umständen zu starten.
Zum Beispiel wenn Sie Threads verwenden eine vordefinierte, lange ausgeführte Aufgabe zu bewältigen. Sie sollten vermeiden, laufen Schleife ab.
Schleife ist nur erforderlich, wenn Sie eine Menge von anderen Interaktionen mit dem Thread haben wollen. Beispielsweise sind die folgenden Bedingungen:
Verwenden Sie Anschluss oder definieren Sie eigene Eingangsquelle zur Kommunikation mit anderen threads
Timer, die Verwendung von threads
Kakao verwenden egal welche PerformSelector... Die Methode
Fäden, die in regelmäßigen Abständen arbeiten zu machen
Angenommen Sie, Sie laufen Schleife in Ihrem Programm verwenden möchten. Dann ist es sehr einfach zu konfigurieren und starten.
Wie bei allen Thread-Programmierung. Sie müssen die Situation planen wo der Worker-Thread der Thread beendet.
Es ist oft besser, einen Thread natürlich als zu zwingen das ganze beenden zu lassen.
Lernen Sie den Link zur Prüfung:
- Http://Blog.CSDN.NET/ztp800201/article/Details/9240913
- Http://www.360doc.com/Content/16/0302/04/31139390_538698652.shtml
- Http://www.cnblogs.com/CQB-Learner/p/5859431.HTML
IOS-Run-Loop lernen Zusammenfassung