Swift Language
Gestion de la mémoire
Recherche…
Introduction
Unmanaged
] [1]. [1]: https://developer.apple.com/reference/swift/unmanaged
Remarques
Quand utiliser le mot-clé faible:
Le mot-cléweak
doit être utilisé si un objet référencé peut être désalloué pendant la durée de vie de l'objet contenant la référence. Quand utiliser le mot-clé sans propriétaire:
Leunowned
clé unowned
propriétaire doit être utilisé si un objet référencé n'est pas censé être désalloué pendant la durée de vie de l'objet contenant la référence. Pièges
Une erreur fréquente est d'oublier de créer des références à des objets, qui doivent survivre à la fin d'une fonction, comme les gestionnaires de lieu, les gestionnaires de mouvement, etc.Exemple:
class A : CLLocationManagerDelegate
{
init()
{
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.startLocationUpdates()
}
}
Cet exemple ne fonctionnera pas correctement, car le gestionnaire d'emplacement est désalloué après le retour de l'initialiseur. La solution appropriée consiste à créer une référence forte en tant que variable d’instance:
class A : CLLocationManagerDelegate
{
let locationManager:CLLocationManager
init()
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.startLocationUpdates()
}
}
Cycles de référence et références faibles
Un cycle de référence (ou cycle de conservation ) est nommé ainsi car il indique un cycle dans le graphe d'objet :
Chaque flèche indique un objet en retenant un autre (une référence forte). À moins que le cycle ne soit rompu, la mémoire de ces objets ne sera jamais libérée .
Un cycle de conservation est créé lorsque deux instances de classes se réfèrent l'une à l'autre:
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
Les deux instances resteront en vie jusqu'à la fin du programme. Ceci est un cycle de rétention.
Références faibles
Pour éviter les cycles de rétention, utilisez le mot-clé weak
ou sans unowned
lors de la création de références pour les cycles de retenue.
class B { weak var a: A? = nil }
Des références faibles ou non acquises n'augmenteront pas le nombre de références d'une instance. Ces références ne contribuent pas à conserver les cycles. La référence faible devient nil
lorsque l'objet référencé est désalloué.
a.b = b // a retains b
b.a = a // b holds a weak reference to a -- not a reference cycle
Lorsque vous travaillez avec des fermetures, vous pouvez également utiliser weak
listes de capture weak
ou unowned
.
Gestion de la mémoire manuelle
Lors de l’interfaçage avec les API C, il est possible de désactiver le compteur de référence Swift. Cela se fait avec des objets non gérés.
Si vous devez fournir un pointeur de type puned à une fonction C, utilisez la méthode toOpaque
de la structure Unmanaged
pour obtenir un pointeur brut et fromOpaque
pour récupérer l'instance d'origine:
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()
}
Notez que si vous utilisez passUnretained
et ses homologues, il est nécessaire de prendre toutes les précautions comme avec les références non- unowned
.
Pour interagir avec les API Objective-C héritées, il peut être nécessaire d'affecter manuellement le nombre de références d'un objet donné. Pour cela, Unmanaged
a retain
et release
méthodes respectives. Néanmoins, il est passRetained
utiliser passRetained
et takeRetainedValue
, qui effectuent des conservations avant de renvoyer le résultat:
func preferredFilenameExtension(for uti: String) -> String! {
let result = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension)
guard result != nil else { return nil }
return result!.takeRetainedValue() as String
}
Ces solutions doivent toujours être le dernier recours et les API natives doivent toujours être préférées.