Swift Language
Speicherverwaltung
Suche…
Einführung
Unmanaged ] [1] verwendet werden. [1]: https://developer.apple.com/reference/swift/unmanaged
Bemerkungen
Wann das schwache Schlüsselwort verwendet wird:
Dasweak Schlüsselwort sollte verwendet werden, wenn ein Objekt, auf das verwiesen wird, während der Lebensdauer des Objekts freigegeben werden kann, das die Referenz enthält. Wann wird das nicht besetzte Schlüsselwort verwendet:
Dasunowned -keyword sollte verwendet werden, wenn nicht erwartet wird, dass ein Objekt, auf das verwiesen wird, während der Lebensdauer des Objekts freigegeben wird, das die Referenz enthält. Fallstricke
Ein häufiger Fehler ist das Vergessen, Verweise auf Objekte zu erstellen, die nach dem Ende einer Funktion weiterleben müssen, z. B. Positionsmanager, Bewegungsmanager usw.Beispiel:
class A : CLLocationManagerDelegate
{
init()
{
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.startLocationUpdates()
}
}
Dieses Beispiel funktioniert nicht ordnungsgemäß, da der Standortmanager nach der Rückkehr des Initialisierers freigegeben wird. Die richtige Lösung ist das Erstellen einer starken Referenz als Instanzvariable:
class A : CLLocationManagerDelegate
{
let locationManager:CLLocationManager
init()
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.startLocationUpdates()
}
}
Referenzzyklen und schwache Referenzen
Ein Referenzzyklus (oder Retentionszyklus ) wird so genannt, weil er einen Zyklus in der Objektgrafik angibt:

Jeder Pfeil zeigt an, dass ein Objekt ein anderes behält (starke Referenz). Wenn der Zyklus nicht unterbrochen wird, wird der Speicher für diese Objekte niemals freigegeben .
Ein Haltezyklus wird erstellt, wenn zwei Instanzen von Klassen aufeinander verweisen:
class A { var b: B? = nil }
class B { var a: A? = nil }
let a = A()
let b = B()
a.b = b // a retains b
b.a = a // b retains a -- a reference cycle
Bei beiden Instanzen bleiben sie bis zum Ende des Programms erhalten. Dies ist ein Haltezyklus.
Schwache Referenzen
Um unowned zu vermeiden, verwenden unowned beim Erstellen von Referenzen das Schlüsselwort weak oder nicht unowned , um die unowned .
class B { weak var a: A? = nil } Schwache oder nicht besetzte Referenzen erhöhen die Referenzanzahl einer Instanz nicht. Diese Referenzen tragen nicht dazu bei, Zyklen einzuhalten. Die schwache Referenz wird zu nil wenn das Objekt, auf das sie verweist, freigegeben wird.
a.b = b // a retains b
b.a = a // b holds a weak reference to a -- not a reference cycle
Wenn Sie mit Verschlüssen arbeiten, können Sie auch weak und nicht unowned Capture-Listen verwenden .
Manuelle Speicherverwaltung
Wenn Sie mit C-APIs arbeiten, möchten Sie möglicherweise den Referenzzähler von Swift deaktivieren. Dies wird mit nicht verwalteten Objekten erreicht.
Wenn Sie einen Typ-punned Zeiger auf eine C - Funktion zu liefern, verwenden toOpaque Verfahren der Unmanaged Struktur einen Rohzeiger zu erhalten, und fromOpaque die ursprüngliche Instanz zu erholen:
setupDisplayLink() {
let pointerToSelf: UnsafeRawPointer = Unmanaged.passUnretained(self).toOpaque()
CVDisplayLinkSetOutputCallback(self.displayLink, self.redraw, pointerToSelf)
}
func redraw(pointerToSelf: UnsafeRawPointer, /* args omitted */) {
let recoveredSelf = Unmanaged<Self>.fromOpaque(pointerToSelf).takeUnretainedValue()
recoveredSelf.doRedraw()
}
Beachten Sie, dass Sie bei Verwendung von passUnretained und Gegenstücken alle Vorsichtsmaßnahmen wie bei unowned Referenzen unowned .
Um mit älteren Objective-C-APIs zu interagieren, sollte der Referenzzähler eines bestimmten Objekts manuell beeinflusst werden. Für das Unmanaged entsprechende Methoden retain und release . Nichtsdestotrotz ist es wünschenswert, passRetained und takeRetainedValue , die die takeRetainedValue durchführen, bevor das Ergebnis zurückgegeben wird:
func preferredFilenameExtension(for uti: String) -> String! {
let result = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension)
guard result != nil else { return nil }
return result!.takeRetainedValue() as String
}
Diese Lösungen sollten immer der letzte Ausweg sein, und sprachnative APIs sollten immer bevorzugt werden.