Stellen Sie sich die folgende Situation vor: Sie haben eine Hintergrundaufgabe (der Begriff "Aufgabe" bedeutet hier eine zufällige Recheneinheit, keine NSTask!), die mit einer der modernen Technologien wie Grand Central Dispatch oder Operation Queues implementiert wird. Ein Controllerobjekt im Hauptthread möchte den Fortschritt dieser Hintergrundaufgabe überwachen und einem Benutzer melden.
Der Fortschritt der Aufgabe kann folgende Eigenschaften haben:
Welches Design passt am besten zu diesen Anforderungen, während es das meiste Cocoa-ish ist?
Bevor Sie die Aufgabe starten, setzen Sie Ihr Controller-Objekt als Delegat.
%Vor%Tatsächlich habe ich diese Vorlage viele Male erfolgreich benutzt, aber es fühlt sich ein wenig zu ausführlich an.
Sehr ähnlich wie Delegierung, aber Code bleibt an einer Stelle.
%Vor%In diesem Fall muss das Hintergrundaufgabenobjekt zwei ähnliche Eigenschaften haben:
%Vor%Und ein Client (unser Controller-Objekt) sollte sich als Beobachter dieser Eigenschaften festlegen. Der Hauptfehler, den ich in dieser Lösung sehe, ist, dass KVO-Benachrichtigungen immer auf demselben Thread ankommen, der die Änderung verursacht hat. Sie können zwar erzwingen, dass Ihre Observer (Callback) -Methode in einer bestimmten GCD-Warteschlange ausgeführt wird, dies ist jedoch möglicherweise nicht immer sinnvoll.
Hintergrundaufgabe sendet Benachrichtigungen und Client hört auf sie.
Gibt es noch andere Muster, die auf diese Situation anwendbar sind? Welche Lösung kann als modernster und Cocoa-ish behandelt werden?
Was ist der Cocoa-Weg, um den Fortschritt einer Hintergrundaufgabe zu beobachten? Ich würde Delegation und NSNotificationCenter sagen, weil Blöcke und KVO später eingeführt wurden und daher ursprünglich nicht existierten die ersten Cocoa-Code-Schreibjahre. Tatsächlich waren optionale Protokollmethoden auch in früheren Objc-Versionen nicht vorhanden, alles war standardmäßig erforderlich.
Daraus kann man sehen, dass Blöcke eine einfachere Möglichkeit sind, Ad-hoc-Delegaten zu implementieren, wobei der Empfänger des Blocks deklariert, welche Parameter an den Block übergeben werden, und Sie können mit ihnen in tun, was Sie wollen Dein -Block. Und KVO scheint ein weniger gebräuchlicher Weg zu sein, NSNotification mit einem standardisierten Ansatz für Eigenschaften zu implementieren, nützlich für den Beitritt der UI, die früher Interfacebilder genannt wurde, und vereinfacht die "was Hölle muss ich tun, um zu wissen, wenn dieser Wert " ändert, der eine Menge Dokumentation mit NSNotification und langen Konstanten erfordert.
Aber ich denke immer noch, dass es für jede dieser Techniken Orte gibt: Blöcke sind gut für Mini-Adhoc-Protokolle, wären aber eine ernsthafte Störung, wenn Sie einen mittleren oder höheren Schnittstellenbereich oder eine bidirektionale Schnittstelle benötigen und KVO nicht Hilfe beim Beobachten von globalen Variablen oder Werten außerhalb einer Klasse / eines Objekts oder von Dingen, die nicht Teil Ihrer öffentlichen Schnittstelle sein sollen.
Also meine definitive Antwort ist:
Wie immer, wählen Sie das beste Werkzeug für jedes Problem, und denken Sie, ich bin schuldig, alle oben genannten auf keine der vorgeschlagenen Weisen zu implementieren!
Bei der Art der Aufgabe, die Sie beschreiben, ist NSNotificationCenter
die beste Option für ein generisches Muster. Der Grund ist, dass man im Allgemeinen nicht wissen kann, wie viele externe Beobachter es gibt. Das Benachrichtigungssystem unterstützt bereits eine beliebige Anzahl von Beobachtern für ein Ereignis, während die anderen Nicht-Abfrageoptionen (Delegierung und Blöcke) typischer Eins-zu-eins sind, es sei denn, Sie führen zusätzliche Arbeiten zur Unterstützung mehrerer Registrierungen durch.
Wie Sie selbst festgestellt haben, ist Umfragen eine schlechte Idee, wenn Sie es vermeiden können.
Nach meiner Erfahrung sind Delegation oder Block-Callback die besten Wahlmöglichkeiten. Die Wahl des einen über den anderen wird meist dadurch bestimmt, welcher Code für die jeweilige Situation besser geeignet ist. Beide sind asynchron. Blockrückrufe reduzieren normalerweise die Notwendigkeit zusätzlicher Instanzvariablen, da Blöcke Variablen in ihrem Gültigkeitsbereich erfassen. Natürlich ist es für beide wichtig zu wissen, auf welchem Thread der Callback ausgeführt wird oder die Delegate-Methode aufgerufen wird.
Ich würde mit KVO gehen, weil Sie es kostenlos bekommen, wenn Sie @properties grundsätzlich verwenden. ABER Ich würde nicht empfehlen, einfache KVO zu verwenden. weil das immer aufrufen wird - observerValueOfKeyPath ... und wenn du mehrere Schlüsselpfade beobachtest, wird es lästig zu warten. Du hast diese Megafunktion mit vielen if (keyPath == bla) ......
Ich empfehle MAKVONotificationCenter von MikeAsh dafür. Es erspart Ihnen auch viele Abstürze, wenn Sie vergessen, einen Beobachter zu entfernen, wenn Sie ihn nicht mehr benötigen.
Tags und Links multithreading grand-central-dispatch cocoa key-value-observing