Sammlungen von nullstellenden schwachen Referenzen unter ARC
Wie kann ich ein array von Nullung schwache Referenzen unter ARC? Ich möchte nicht, das array zu behalten die Objekte. Und ich möchte den array-Elementen entweder sich zu entfernen, wenn Sie freigegeben ist, oder legen Sie diese Einträge gleich null.
Ähnlich, wie ich es machen kann, mit einem Wörterbuch? Ich will nicht das Wörterbuch behalten die Werte. Und wieder möchte ich die dictionary-Elemente entweder sich zu entfernen, wenn die Werte werden freigegeben, oder setzen Sie die Werte auf nil. (Ich behalten müssen, die Schlüssel, die die eindeutigen Kennungen, zumindest bis die entsprechenden Werte werden freigegeben.)
Diesen beiden Fragen befassen sich mit ähnlichen Boden:
Aber weder ist gefragt, für Nullung Referenzen.
Pro die Dokumentation, weder NSPointerArray noch NSHashMap Unterstützung schwacher Referenzen unter ARC. NSValue ist nonretainedObjectValue wird nicht funktionieren, entweder, wie es ist nicht null.
Die einzige Lösung, die ich sehe, ist das erstellen meine eigenen NSValue-wie wrapper-Klasse mit einem (weak)
Eigenschaft, als diese Antwort erwähnt, in der Nähe des Ende. Gibt es einen besseren Weg, ich bin nicht zu sehen?
Ich bin für die Entwicklung für OS X 10.7 und iOS 6.0.
InformationsquelleAutor der Frage paulmelnikow | 2013-01-08
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nullung schwache Referenzen erfordert OS X 10.7 oder iOS 5.
Können Sie nur definieren, schwache Variablen im code, ivars oder blockiert. AFAIK gibt es keine Möglichkeit, dynamisch (zur Laufzeit) erstellen Sie eine schwach variable, weil LICHTBOGEN wirksam wird, während der Kompilierung. Wenn Sie den code ausführen, er hat bereits die behält und releases Hinzugefügt.
Gesagt haben, dass kann man wohl Missbrauch Blöcke, um eine Wirkung wie dieser.
Haben einen block, gibt einfach die Referenz.
Beachten Sie, dass Sie brauchen, um zu kopieren Sie den block, um es kopiert auf den heap.
Nun können Sie zu Fuß die array-Wann immer Sie wollen, dealloc ' ed Objekte in Blöcke return nil. Sie können dann entfernen Sie diese.
Können Sie code automatisch ausgeführt werden, wenn der schwache ref eingeschossen. Wenn dies ist, was Sie wollen, dann können Sie Gebrauch machen von der Funktion der zugehörigen Objekte. Werden diese freigegeben zur gleichen Zeit wie das Objekt, das Sie zugeordnet sind. So konnten Sie Ihre eigenen sentry-tag informiert die schwachen Sammlung von Informationen über die Objekte Untergang.
Würden Sie einem Objekt zugeordnet zu beobachten, für die dealloc (falls der Verein ist die einzige Referenz) und das zugehörige Objekt über einen Zeiger auf die Sammlung zu beobachten. Dann in die Wache dealloc rufen Sie die schwache Erhebung zu informieren, dass das beobachtete Objekt gegangen.
Hier ist mein Kommentar auf zugehörige Objekte: http://www.cocoanetics.com/2012/06/associated-objects/
Hier ist meine Umsetzung:
Dieser wäre wie folgt verwendet:
wenn Sie die Ausgabe allObjects innerhalb der autorelease-pool blockieren, dann haben Sie zwei Objekte. Außerhalb, haben Sie nur die Zeichenfolge.
Fand ich, dass in der dealloc der Eintrag der Objekt-Referenz ist bereits null, so dass Sie nicht verwenden können __schwach. Stattdessen bin ich mit der Speicheradresse des Objekts als hash. Während diese noch in _entries betrachten Sie Sie als eigentliche Objekt und die allObjects liefert einen autoreleased array von starken Referenzen.
Hinweis: dies ist nicht thread-sicher. Viel zu tun mit dealloc auf nicht-Haupt-queues/threads würden Sie brauchen, vorsichtig zu sein, synchronisieren Sie den Zugriff auf und mutiert die interne _entries gesetzt.
Hinweis 2: Das funktioniert bisher nur mit Objekten die überprüfung in einem einzigen schwachen Sammlung da eine zweite check-in überschreibt die zugehörigen sentry. Wenn Sie brauchte diese mit mehreren schwachen Sammlungen dann die sentry stattdessen sollte ein array von diesen Sammlungen.
Anmerkung 3: ich habe die sentry ' s Verweis auf die Sammlung zu schwach als auch zu vermeiden, einen Zyklus behalten.
Hinweis 4: Hier sind ein typedef und Hilfsfunktionen, die sich mit der block-syntax für Sie:
InformationsquelleAutor der Antwort Cocoanetics
Hier ist code für eine ein-Nullstellung schwach-reference-wrapper-Klasse. Es funktioniert einwandfrei mit NSArray, NSSet, NSDictionary.
Der Vorteil dieser Lösung ist, dass es kompatibel mit älteren OS ' s und das ist es einfach. Der Nachteil ist, dass bei der Iteration, werden Sie wahrscheinlich benötigen, um zu überprüfen, dass
-nonretainedObjectValue
ist nicht-null, bevor Sie es.Es ist die gleiche Idee wie der wrapper im ersten Teil Cocoanetics' Antwort, die verwendet Blöcke, um das gleiche erreichen.
WeakReference.h
WeakReference.m
InformationsquelleAutor der Antwort paulmelnikow
NSMapTable
sollte für Sie arbeiten. Verfügbar in iOS 6.InformationsquelleAutor der Antwort Tricertops
Ausgabe:
Bearbeiten: ich erstellte eine Probe schwach map collection von Grund auf basierend auf dieser Idee. Es funktioniert, aber es ist hässlich, hat mehrere Gründe:
Habe ich eine Kategorie NSObject hinzufügen @Eigenschaften für den Schlüssel,die nächste map Eimer, und einen Verweis auf die Auflistung der Besitz des Objekts.
Sobald Sie null-das Objekt verschwindet aus der Auflistung.
ABER für die Karte zu haben, eine dynamische Kapazität, die es braucht, um ein update erhalten die Anzahl der Elemente zur Berechnung der Auslastung und Erweiterung der Kapazität, wenn nötig. Es sei denn, Sie möchten, führen Sie einen Θ(n) update Durchlaufen das gesamte array jedes mal, wenn Sie ein element hinzuzufügen. Ich Tat dies mit einem Rückruf auf die dealloc-Methode der Beispiel-Objekt, ich bin das hinzufügen, um die Sammlung. Ich konnte das original Bearbeiten-Objekt (das ich der Kürze halber) oder Erben von einer Oberklasse oder swizzle die dealloc. In jedem Fall hässlich.
Jedoch, wenn Sie nichts dagegen haben, dass eine Feste Kapazität Sammlung, die Sie nicht brauchen, die Rückrufe. Die Sammlung setzt separate chaining und unter der Annahme einer gleichmäßigen Verteilung der hash-Funktion, Leistung wird Θ(1+n/m) n=Elemente,m=Kapazität. Aber (mehr aber) zu vermeiden, bricht die Verkettung benötigen Sie noch eine frühere Verbindung als eine Kategorie für @property und einen link auf das nächste element in der dealloc des Elements. Und wenn wir berühren die dealloc, es ist nur als gut zu informieren, die Erhebung, dass das element entfernt wird (was Sie jetzt tut).
Schließlich ist zu beachten, dass der test im Projekt ist minimal und ich hätte etwas übersehen.
InformationsquelleAutor der Antwort Jano
Ich nur erstellen, nicht Thread-sichere schwach ref version von NSMutableDictionary und NSMutableSet. Code hier: https://gist.github.com/4492283
Für NSMutableArray, die Dinge mehr kompliziert, weil es sich nicht enthalten
nil
und ein Objekt dem array Hinzugefügt werden mehrmals. Aber es ist machbar, umgesetzt.InformationsquelleAutor der Antwort Bryan Chen
Fügen Sie einfach eine Kategorie für NSMutableSet mit folgenden code:
Gleichen Weg, um eine Kategorie zu erstellen für NSMutableArray und NSMutableDictionary.
Entfernen dealloc Referenz in didReceiveMemoryWarning besser sein wird.
Dann, was Sie tun sollten, ist zum aufrufen
addWeakReference:
für Ihre container-Klasse.InformationsquelleAutor der Antwort simalone
Wenn Sie mit mindestens MacOS X 10.5 oder iOS6, dann:
Beachten Sie, dass die Kollektionen, die unter Umständen nicht sofort bemerken, dass Gegenstände verschwunden, so zählt könnte noch höher sein, und die Tasten könnten noch existieren, obwohl das zugehörige Objekt Weg ist, usw. NSPointerArray hat eine kompakte Methode, die sollte in der Theorie loszuwerden, keine null-Werte zulässig sind Zeiger. NSMapTable docs beachten Sie, dass die Schlüssel für weakToStrong Karten bleiben in der Tabelle (auch wenn effektiv null), bis es geändert wird, d.h. die starke Objekt-pointers kann im Speicher verbleiben, auch wenn Sie nicht mehr logisch verwiesen werden.
Edit: ich sehe, dass das ursprüngliche Plakat bat, über ARC. Ich glaube, es war in der Tat 10.8 und iOS 6, bevor die Behälter mit ARC -- die Vorherige "schwachen" Zeug war für die GC, glaube ich. ARC nicht unterstützt, bis 10.7, also es ist wirklich eine Frage, wenn Sie brauchen, um Unterstützung für das release und nicht 10.6, in welchem Fall würden Sie brauchen, um Rollen Sie Ihre eigenen (oder vielleicht verwenden Sie benutzerdefinierte Funktionen mit NSPointerFunctions, die dann wiederum eingesetzt werden, mit NSPointerArray, NSHashTable, und NSMapTable).
InformationsquelleAutor der Antwort Carl Lindberg
Sehen die BMNullableArray Klasse, die ein Teil meiner BMCommons Rahmen für eine vollständige Lösung für dieses problem.
Diese Klasse ermöglicht das null-Objekte eingefügt werden und die Möglichkeit hat, zu schwach Referenz der Objekte, die es enthält, (automatisch nilling Sie erhalten, wenn Sie freigegeben ist).
Das problem mit der automatischen removal (welche ich versucht habe umzusetzen) ist, dass Sie thread-Fragen der Sicherheit, da es nicht garantiert ist, zu welchem Zeitpunkt die Objekte werden freigegeben, das könnte aber auch passieren, während Sie Durchlaufen das array.
Diese Klasse ist eine Verbesserung gegenüber NSPointerArray, da es einige abstracts unteren Ebene details für Sie und ermöglicht Ihnen die Arbeit mit Objekten anstelle von Zeigern. Es unterstützt sogar NSFastEnumeration Iteration über das array mit null Referenzen drin.
InformationsquelleAutor der Antwort Werner Altewischer