Tout d'abord, notez que vous n'avez généralement pas besoin de s'inquiéter à propos de conserver cycles, DispatchQueue.main.asyncAfter
, que la fermeture sera exécuté sur certains point. Donc si vous avez ou non faiblement capture self
, vous ne serez pas en création permanente d'un cycle de conserver (en supposant que l' tickle.fresh
n'a pas également).
Si ou pas vous mettre un [weak self]
liste de capture sur l'extérieur, asyncAfter
fermeture dépend entièrement de vous souhaitez self
à être conservées jusqu'à la clôture est appelé (après le temps que vous). Si vous n'avez pas besoin d' self
pour rester en vie jusqu'à la clôture est appelé, mis [weak self]
en, si vous le faites, alors ne pas le mettre.
Si ou pas vous mettre un [weak self]
sur la partie intérieure de la clôture, l'on est passé de tickle.fresh
) dépend si vous avez déjà faiblement capturé self
à l'extérieur de la clôture. Si vous n'avez pas, alors vous pouvez mettre [weak self]
afin de prévenir l'intérieur de la fermeture de son maintien. Si toutefois, à l'extérieur de fermeture a déjà faiblement capturé self
, puis l'intérieur de la fermeture va déjà avoir une faible référence à l' self
, donc l'ajout d' [weak self]
à l'intérieur de la fermeture n'aura aucun effet.
Donc, pour résumer:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { msg in
self.paint()
}
}
self
sera conservé par à la fois l'extérieur et l'intérieur de la clôture.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { msg in
self?.paint()
}
}
self
ne seront pas conservées par la fermeture.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { [weak self] msg in
self?.paint()
}
}
Même que ci-dessus, la plus - [weak self]
pour l'intérieur de la fermeture n'a pas d'effet, comme self
est déjà faiblement captée par l'extérieur de la clôture.
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { [weak self] msg in
self?.paint()
}
}
self
sera conservé par l'extérieur de fermeture, mais pas à l'intérieur de la clôture.
Bien sûr, il pourrait être que vous ne voulez pas self
à être conservé par l'extérieur de fermeture, mais vous ne voulez qu'il soit conservé par l'intérieur de la clôture. Dans de tels cas, vous pouvez déclarer une variable locale à l'extérieur de fermeture, afin de maintenir une référence forte à l' self
,, où vous pouvez alors saisir dans l'intérieur de la fermeture:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
guard let strongSelf = self else { return }
tickle.fresh { msg in
strongSelf.paint()
}
}
Maintenant, self
de ne pas être maintenu en vie par l'extérieur de fermeture, mais une fois qu'il est appelé, si self
existe toujours, il sera maintenu en vie par l'intérieur de la fermeture jusqu'à ce que la fermeture a été libéré.
En réponse à:
Est une référence forte à une référence faible, une faible ou une forte référence?
Références faibles sont mis en œuvre comme des options, qui sont des types de valeur. Par conséquent, vous ne pouvez pas directement avoir une référence forte à l'un – à la place, vous devez d'abord ouvrir le cadeau, puis de prendre une référence forte à l'instance sous-jacente. Dans ce cas, vous êtes tout simplement traitant avec une référence forte (exactement comme mon exemple ci-dessus avec strongSelf
).
Toutefois, si une référence faible est en boîte (ce qui arrive avec la fermeture de capture – le type de valeur doit être mis dans un segment de mémoire allouée à cocher) – alors vous pouvez en effet avoir une forte référence à cette zone. L'effet de ceci est équivalent à une faible référence à l'instance originale, vous avez juste un invisible peu plus d'indirection.
En fait, c'est exactement ce qui se passe dans l'exemple où l'extérieur fermeture faiblement capture self
et l'intérieur de la fermeture "fortement capture" qui référence faible. L'effet est que ni la fermeture conserve self
.