Ich möchte eine Reihe schwacher Referenzen in Swift speichern. Das Array selbst sollte keine schwache Referenz sein - seine Elemente sollten es sein. Ich denke, Cocoa NSPointerArray
bietet eine nicht typsichere Version davon.
179
Ich möchte eine Reihe schwacher Referenzen in Swift speichern. Das Array selbst sollte keine schwache Referenz sein - seine Elemente sollten es sein. Ich denke, Cocoa NSPointerArray
bietet eine nicht typsichere Version davon.
Antworten:
Erstellen Sie einen generischen Wrapper als:
Fügen Sie Ihrem Array Instanzen dieser Klasse hinzu.
Bei der Definition können
Weak
Sie entwederstruct
oder verwendenclass
.Um das Ernten von Array-Inhalten zu erleichtern, können Sie Folgendes tun:
Die Verwendung von
AnyObject
oben sollte durch ersetzt werdenT
- aber ich denke nicht, dass die aktuelle Swift-Sprache eine als solche definierte Erweiterung zulässt.quelle
Stuff
durch ein Protokoll ersetzen . siehe diese verwandte FrageSie können die NSHashTable mit schwachObjectsHashTable verwenden.
NSHashTable<ObjectType>.weakObjectsHashTable()
Für Swift 3:
NSHashTable<ObjectType>.weakObjects()
NSHashTable-Klassenreferenz
quelle
Any
aber nichtAnyObject
, wie Protokolle.MyProtocol: class
undNSHashTable<MyProtocol>.weakObjects()
. "'NSHashTable' erfordert, dass 'MyProtocol' ein Klassentyp ist.Es ist etwas spät für die Party, aber probieren Sie meine. Ich habe als Set kein Array implementiert.
WeakObjectSet
Verwendung
Beachten Sie, dass WeakObjectSet keinen String-Typ, sondern NSString verwendet. Weil der String-Typ kein AnyType ist. Meine schnelle Version ist
Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
.Code kann von Gist abgerufen werden. https://gist.github.com/codelynx/30d3c42a833321f17d39
** HINZUGEFÜGT IM NOV.2017
Ich habe den Code auf Swift 4 aktualisiert
Wie Gokeji erwähnte, habe ich herausgefunden, dass NSString aufgrund des verwendeten Codes nicht freigegeben wird. Ich kratzte mir am Kopf und schrieb die MyString-Klasse wie folgt.
Dann ersetzen Sie
NSString
mitMyString
so. Dann seltsam zu sagen, dass es funktioniert.Dann fand ich eine seltsame Seite, die möglicherweise mit diesem Problem zusammenhängt.
https://bugs.swift.org/browse/SR-5511
Es heißt, das Problem sei,
RESOLVED
aber ich frage mich, ob dies noch mit diesem Problem zusammenhängt. Wie auch immer, Verhaltensunterschiede zwischen MyString oder NSString liegen außerhalb dieses Kontexts, aber ich würde mich freuen, wenn jemand dieses Problem herausfinden würde.quelle
nil
Werte aus dem internen zu entfernenSet
. Deshalb habe ich einereap()
in der oberen Antwort erwähnte Funktion hinzugefügt und sichergestellt, dass sie beireap()
jedemWeakObjectSet
Zugriff aufgerufen wird.nil
nicht mehr wirdNSString
dies nicht der Fall ist.UnsafeMutablePointer<T>(&object)
, zufällig ändern kann (dasselbe gilt fürwithUnsafePointer
). Ich verwende jetzt eine Version, die von a unterstützt wirdNSHashTable
: gist.github.com/simonseyer/cf73e733355501405982042f760d2a7d .Das ist nicht meine Lösung. Ich habe es in den Apple Developer Forums gefunden .
@GoZoner hat eine gute Antwort, aber es stürzt den Swift-Compiler ab.
Hier ist eine Version eines Containers für schwache Objekte, die den aktuell veröffentlichten Compiler nicht zum Absturz bringt.
Sie können dann ein Array dieser Container erstellen:
quelle
EXC_BAD_ACCESS
für mich. Mit Klasse funktioniert gutSie können dies tun, indem Sie ein Wrapper-Objekt erstellen, das einen schwachen Zeiger enthält.
Und diese dann im Array verwenden
quelle
class
, umweak
vars zu benutzenprotocol Protocol : class { ... }
Wie wäre es mit funktionalem Wrapper?
Rufen Sie einfach die zurückgegebene Schließung an, um zu überprüfen, ob das Ziel noch am Leben ist.
Und Sie können diese Verschlüsse in einem Array speichern.
Und Sie können die schwach erfassten Werte abrufen, indem Sie die Aufrufe der Schließungen zuordnen.
Eigentlich brauchen Sie keine Funktion, um einen Abschluss zu machen. Erfassen Sie einfach ein Objekt direkt.
quelle
var array: [(x: Int, y: () -> T?)]
. Genau das, wonach ich gesucht habe.let values = Array(array1.map({ $0() })) part
. Da dies kein Array von Abschlüssen mit schwachen Referenzen mehr ist, bleiben die Werte erhalten, bis die Zuordnung dieses Arrays aufgehoben wird. Wenn ich richtig liege, ist es wichtig zu beachten, dass Sie dieses Array niemals so beibehalten sollten,self.items = Array(array1.map({ $0() }))
da dies den Zweck übertrifft.Ich hatte die gleiche Idee, einen schwachen Container mit Generika zu erstellen.
Als Ergebnis habe ich einen Wrapper erstellt für
NSHashTable
:Verwendung:
Es ist nicht die beste Lösung, da
WeakSet
es mit jedem Typ initialisiert werden kann. Wenn dieser Typ nicht demAnyObject
Protokoll entspricht, stürzt die App aus detaillierten Gründen ab. Aber ich sehe momentan keine bessere Lösung.Die ursprüngliche Lösung bestand darin, Folgendes zu definieren
WeakSet
:In diesem Fall
WeakSet
kann jedoch nicht mit dem Protokoll initialisiert werden:Derzeit kann der obige Code nicht kompiliert werden (Swift 2.1, Xcode 7.1).
Aus diesem Grund habe ich die Anpassung eingestellt
AnyObject
und zusätzliche Wachen mitfatalError()
Behauptungen hinzugefügt .quelle
Einzelheiten
Lösung
Option 1
Option 1 Verwendung
Option 2
Option 2 Verwendung
Vollständige Probe
quelle
protocol TP: class { } class TC { var a = WeakArray<TP>() var b = WeakObjectsArray<TP>() }
protocol TP: class { } class TC<TYPE> where TYPE: TP { var a = WeakObjectsArray<TYPE>() // Use like regular array. With any objects var weakObjectsArray = [TYPE?]() }
delegates
. Dann hätten Sie einige View Controller, die diese Funktionalität nutzen möchten. Sie würden erwarten, anzurufenMyManager.delegates.append(self)
. WennMyManager
es jedoch an einen generischen Typ gebunden ist, ist dies nicht sehr brauchbar.protocol TP: class { } class MyManager { typealias Delegate = AnyObject & TP static var delegates = [Delegate?]() } class A: TP { } class B: TP { } //MyManager.delegates.append(A()) //MyManager.delegates.append(B())
Das vorhandene Beispiel für den WeakContainer ist hilfreich, aber es hilft nicht wirklich, schwache Referenzen in vorhandenen schnellen Containern wie Listen und Wörterbüchern zu verwenden.
Wenn Sie List-Methoden wie Contain verwenden möchten, muss der WeakContainer Equatable implementieren. Also habe ich den Code hinzugefügt, damit der WeakContainer gleichwertig ist.
Für den Fall, dass Sie den WeakContainer in Wörterbüchern verwenden möchten, habe ich ihn auch hashbar gemacht, damit er als Wörterbuchschlüssel verwendet werden kann.
Ich habe es auch in WeakObject umbenannt, um zu betonen, dass dies nur für Klassentypen gilt, und um es von den WeakContainer-Beispielen zu unterscheiden:
Auf diese Weise können Sie einige coole Dinge tun, z. B. ein Wörterbuch mit schwachen Referenzen verwenden:
quelle
Hier ist , wie @ GoZoner die große Antwort machen entsprechen
Hashable
, so dass es indiziert werden können in Container - Objekte wie:Set
,Dictionary
,Array
etc.quelle
Da
NSPointerArray
das meiste davon bereits automatisch erledigt wird, habe ich das Problem gelöst, indem ich einen typsicheren Wrapper dafür erstellt habe, der in anderen Antworten viel von der Boilerplate vermeidet:Anwendungsbeispiel:
Es ist mehr Arbeit im Voraus, aber die Verwendung im Rest Ihres Codes ist IMO viel sauberer. Wenn Sie es Array-ähnlicher machen möchten, können Sie sogar Subskription implementieren, es zu einem machen
SequenceType
usw. (aber mein Projekt benötigt nurappend
undforEach
daher habe ich nicht den genauen Code zur Hand).quelle
Eine weitere Lösung für das gleiche Problem ... Der Schwerpunkt dieses Problems liegt auf dem Speichern eines schwachen Verweises auf ein Objekt, aber auch auf dem Speichern einer Struktur.
[Ich bin nicht sicher, wie nützlich es ist, aber es hat eine Weile gedauert, bis die Syntax richtig war]
quelle
Sie könnten einen Wrapper erstellen
Array
. Oder verwenden Sie diese Bibliothek https://github.com/NickRybalko/WeakPointerArray.let array = WeakPointerArray<AnyObject>()
Sie ist typsicher.quelle
Andere Antworten haben den generischen Blickwinkel abgedeckt. Ich dachte, ich würde einen einfachen Code teilen, der das abdeckt
nil
Winkel .Ich wollte ein statisches Array (gelegentlich lesen) aller
Label
s, die derzeit in der App vorhanden sind, wollte es aber nicht sehennil
, wo sich die alten befanden.Nichts Besonderes, das ist mein Code ...
quelle
flatMap
anstelle vonfilter
&map
?Ich habe dies auf die Arbeit von @Eonil gestützt, da ich die Strategie der schwachen Verschlussbindung liebte, aber ich wollte keinen Funktionsoperator für eine Variable verwenden, da sie sich äußerst kontraintuitiv anfühlte
Was ich stattdessen getan habe, ist wie folgt:
Auf diese Weise können Sie Folgendes tun:
quelle
Das ist meine Lösung:
- -
quelle
Dies ist eine typsichere Sammlung, die Container mit schwachen Objekten enthält. Außerdem werden beim Zugriff automatisch keine Container / Wrapper entfernt.
Beispiel:
Die benutzerdefinierte Sammlung https://gist.github.com/djk12587/46d85017fb3fad6946046925f36cefdc
quelle
Was ist mit einem funktionalen Ansatz ?
Dies ist die Hauptidee. Fügen Sie dann eine beliebige Komfortlogik hinzu, um zu verfolgen, was sich im Array befindet. Zum Beispiel könnte man den gleichen Ansatz mit einem Wörterbuch in Betracht ziehen, bei dem der Schlüssel verwendet wird, um herauszufinden, was sich darin befindet.
quelle