iOS 4 GCD Fragen
Habe ich mir einige der Vorträge bilden WWDC 2010 und lese auch die meisten der Dokumente, die auf Blöcke und Parallelität und habe ein paar Fragen bezüglich der Verwendung von Bausteinen mit seriellen queues, die in "Grand Central Dispatch".
Ich habe eine iOS-4-Projekts, das hat eine scrollview und ein Wörterbuch mit Bild-Informationen - urls zu den Bildern und so weiter. Ich will GCD und blockiert den download der Bilder und steckte Sie in meine scrollview daher nicht die Sperrung der Haupt-thread. Ich habe geschrieben das folgenden code, der zu funktionieren scheint:
for (NSDictionary* dict in images)
{
dispatch_async(image_queue, ^{
NSString* urlString = [dict objectForKey:@"url"];
NSURL* url = [NSURL URLWithString:urlString];
NSData* imageData = [[NSData alloc] initWithContentsOfURL:url];
UIImage* image = [UIImage imageWithData:imageData];
UIImageView* imageView = //initialize imageView with image;
dispatch_async(dispatch_get_main_queue(), ^{
[self.scrollView addSubview:imageView];
});
[imageData release];
});
}
Habe ich zwei Fragen:
-
Entsprechend der Parallelität guide sollte ich nicht erfassen Variablen aus dem umgebenden scope, die nicht skalaren Typen in meinem code, den ich erfassen dict ist ein NSDictionary* Objekt. Wenn ich bin nicht erlaubt, es zu erfassen, wie soll ich dann den code schreiben? Hat ein block nur zu erfassen, Variablen aus dem umgebenden scope, die tatsächlich genutzt werden?
-
Was passiert, wenn ich die aktuellen ViewController, bevor alle Bilder abgerufen werden, die über die serielle dispatch queue? Ich glaube nicht, dass Sie sich bewusst sind, dass der ViewController das Sie Weg ist also, was passiert, wenn Sie ausführen, die Fertigstellung handler wo ich das Bild einfügen-Ansichten in meine scrollview auf dem Haupt-thread? Macht es einen Fehler, oder was? Und wie kann ich kündigen, alle übrigen Operationen auf die serielle queue, wenn meine ViewController verschwindet?
Beste Grüße,
- Ich würde gerne sehen, einige best practices auf diese als gut.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Während es eine nagende Punkt, das ist wichtig zu verstehen, was die Parallelität Anleitung versucht, Ihnen zu sagen: Zeiger sind Skalare Typen. So können Sie erfassen Zeiger innerhalb des blocks alles, was Sie wollen... ABER Sie haben bewusst die Lebensdauer der Speicher, den Sie Punkt um! NSDictionary * ist-eine-Art-von-id, und beim Verweis auf eine id in einem block, der Laufzeit übernimmt die Verantwortung für die Beibehaltung der id, wenn der block wird kopiert (es ist von dispatch_async()) und dann loslassen, wenn der block selbst ist freigegeben. Und ja, ein block erfasst nur die Variablen, auf die verwiesen wird, innerhalb es.
Da Sie jetzt wissen, dass die async-block gemacht hat, behalten, auf sich selbst, sollte es klar(er), die (modulo-Speicher-management-Fehler) Ihr ViewController kann nicht "verschwinden", bis der block fertig ist. So wird es nicht zum Absturz bringen-aber Sie sind richtig, um beachten Sie, dass Sie wirklich wollen, eine Möglichkeit zum Abbrechen dieser Art der asynchronen Arbeit, wenn man nicht gerade plant, die Ergebnisse mehr. Eine einfache, aber effektive Muster ist, um eine Prüfung zu Beginn Ihres async-block, der überprüft, um zu sehen, ob die Arbeit sollte trotzdem getan werden.
Da andere beantwortet haben, Ihre beiden Fragen möchte ich kommentieren Sie Ihren code, und empfehlen Ihnen nicht die Verwendung GCD für Netzwerk-Anfragen wie Bilder. Das Hauptproblem mit Ihnen ist, dass Sie alle gleichzeitig laufen. Abhängig von der Anzahl der downloads, die Sie einrichten können, zu viele gleichzeitige verbindungen, die möglicherweise bremst eine Mobilfunkverbindung, und der Benutzer kann am Ende denken somethings falsch, wenn die Bilder nicht zu starten, die, während Sie kämpfen für die kostbare Netzwerk.
Versuchen, eine
NSOperationQueue
mit einemmaxConcurrentOperationCount
den Wert 2 oder 3. Dieses erlaubt Ihnen, eine Warteschlange für potenziell unendliche Menge von Anfragen über das Netzwerk, sondern haben höchstens ein paar parallel ausführen. Da kann man den Zugriff auf den Netzwerk-status des Geräts können Sie bedingt erhöhen, es zu sagen 8 für wifi-verbindungen.Und das zweite problem mit GCD, ist, dass es ein wenig umständlich zu stornieren ausstehende Operationen. Wenn Ihre Benutzer einen view-controller und dann schiebt zurück, je nachdem, wie Sie programmiert haben Ihren code, GCD-Blöcke werden behalten die view-Controllers zu verhindern, dass es freigesetzt wird, und eigentlich alle Netzwerk-Operationen haben bis zum Ende, bis der controller freigesetzt werden kann (also kein Punkt in der Streichung der verbindungen in
dealloc
).Ich lernte auf die harte Weise die überwachung eines proxy und geht schnell, innerhalb einer Ansicht und wieder zurück. Es war wirklich erschreckend zu sehen, wie die ausstehenden verbindungen zugefügt von ungefähr 20 Sekunden zusätzliche Netzwerk-Bandbreite Schaden zu meiner sonst nicht bewusst, Anwendung.
tl;dr benutzen Sie eine Warteschlange für das Netzwerk, GCD für das image processing/scaling/GUI-Aktualisierung.
image_queue
ist, könnte es schon zugewiesendispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)
.@Kaelin Colclasure : zur 1. Frage es scheint wohl eher ein problem der freigegebenen Zustand in Multithread-Anwendung: für integral-Typ Sie haben, eine, Kopie durch den Wert (das gilt für die Zeiger auch), aber wenn Sie ein Objekt verwiesen wird, die von einem Zeiger, Sie haben alle Probleme im Zusammenhang der fehlenden Verriegelung (eine Art variation der Lebensdauer von Objekten problem, das Sie hier erwähnt).
Hier ist der praktische Unterschied bei deinem ersten Punkt:
Wenn ich vorbeigehe, einen Skalar in einem block verwendet, in einem GCD Warteschlange, dann in den block, ich arbeite mit einer Kopie der original-Daten. Änderungen werden nicht sichtbar außerhalb des Blocks. (Gibt es Einschränkungen zu dieser, die
__block
Modifikator für die Instanz aber im Allgemeinen ist dies richtig).Wenn ich gehen, sagen, eine
NSMutableDictionary
in einem block, änderungen im Wörterbuch wird werden sichtbar außerhalb der block-denn Sie erhalten Referenz auf das Wörterbuch nicht nehmen, eine Tiefe Kopie.In beiden Fällen Speicher-management ist für Sie ausgeführt, dass entweder die Skalare variable kopiert werden, oder Objekte werden beibehalten.
Da kann man nicht ändern, den Inhalt einer
NSDictionary
nachdem es initialisiert wurde, werden Sie wahrscheinlich feststellen, dass Blöcke automatisch Das Richtige zu tun für Sie.Auf den zweiten Punkt, das memory-management ist so ziemlich die automatische, es sei denn, Sie brauchen, um eine Kopie der ein veränderliches Objekt.
Gibt es einige Einschränkungen und Anforderungen bewusst zu sein, wenn dabei die BLE-Entwicklung für iOS.
Der erste beinhaltet die iOS-Simulator. Interessanterweise zu einem Zeitpunkt, der iOS-Simulator unterstützt hat, die Bluetooth-Entwicklung (die WWDC 2012-Bluetooth-101 video macht einen Verweis auf diese Funktion hat), aber auf der WWDC 2013, Apple hat angekündigt, dass die Bluetooth-Unterstützung nicht mehr in den Simulator.
Auf der Oberfläche erscheint dies bedauerlich. Jedoch, die Entwicklung auf einem Gerät ist eine bessere und genauere Erfahrung mit BLE. Zusätzlich, da alle iPhones nach dem iPhone 4s (2011) haben Bluetooth-4.0 — und durch die Erweiterung, der BLE die meisten iOS-Entwickler bereits über Geräte, die es unterstützen. Wir fast gar nicht zu Fragen brauchen die Frage nicht mehr, aber es ist gut zu wissen, wer es verwenden kann für den Fall, Sie haben einen eingeschränkten Satz von Geräte-Typen, für die Sie entwickeln apps oder BLE-Geräte.
Weitere wichtige Anforderung, sich zu erinnern, wenn dabei Kern-Bluetooth-Entwicklung ist, dass Apple platziert die Mehrheit die Verantwortung für die Interaktion mit BLE-Geräten auf die app-Entwickler. Sehr wenig wird verwaltet und gepflegt von iOS selbst in Bezug auf die Verwaltung von Bluetooth. Eine Sache, die verwaltet das Betriebssystem ist die Verbindung, die angezeigt wird in den Einstellungen > Bluetooth app.