Il y a question similaire sur la façon de weakify
/strongify
self, qui est répondu, mais je me demande comment utiliser "self" sans dérive vers la droite causée par if let
:
Welcome to Apple Swift version 2.0 (700.0.59 700.0.72). Type :help for assistance.
2> import Foundation
3> class Foo {
4. func guardOptSelf() -> () throws -> Void {
5. return { [weak self] in
6. guard let self = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) }
7. self.doSomethingNonOptionalSelf()
8. }
9. }
10. }
repl.Swift:6:19: error: pattern matching in a condition requires the 'case' keyword
guard let self = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) }
^
case
repl.Swift:6:23: error: binary operator '~=' cannot be applied to two 'Foo?' operands
guard let self = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) }
Vous pouvez shadow self
; vous avez juste besoin de backticks pour indiquer que "vous savez ce que vous faites". Par exemple:
foo.doSomethingAsyncWithBar(bar) { [weak self] result in
guard let `self` = self else { return }
self.receivedResult(result)
}
Ou, dans votre exemple:
2> import Foundation
3> class Foo {
4. func guardOptSelf() -> () throws -> Void {
5. return { [weak self] in
6. guard let `self` = self else { throw NSError(domain: "I was destroyed!", code: 1, userInfo: nil) }
7. self.doSomethingNonOptionalSelf()
8. }
9. }
10. }
Depuis Swift 4.2, vous pouvez utiliser la syntaxe suivante:
{ [weak self] in
guard let self = self else { return }
// self is not an optional anymore, it is held strongly
}
Pour plus d'informations, voir la proposition d'évolution Swift SE-0079 .
Parfois, d'autres approches que l'utilisation de guard let
pourrait également être utile (par exemple, plus court ou plus lisible). Voir aussi la section suivante, remplacez simplement strongSelf
par self
dans quelques exemples.
Car guard let `self` = self
est un bogue du compilateur comme indiqué par Chris Lattner J'essaierais de l'éviter. Dans votre exemple, vous pouvez utiliser un simple chaînage facultatif simple:
return { [weak self] in
self?.doSomethingNonOptionalSelf()
}
Parfois, vous devrez peut-être utiliser self comme paramètre. Dans ce cas, vous pouvez utiliser flatMap
(sur un type facultatif):
{ [weak self] in
self.flatMap { $0.delegate?.tableView($0, didSelectRowAt: indexPath) }
}
Si vous devez faire quelque chose de plus compliqué, vous pouvez utiliser if let
construction:
{ [weak self] in
if let strongSelf = self {
// Do something more complicated using strongSelf
}
}
ou guard let
construction:
{ [weak self] in
guard let strongSelf = self else { return }
// Do something more complicated using strongSelf
}
ou vous pouvez créer une méthode privée:
{ [weak self] in
self?.doSomethingMoreComplicated()
}
...
private func doSomethingMoreComplicated() {
// Do something more complicated
}
Depuis Swift 4.2 vous n'avez plus besoin d'utiliser self avec des backticks (bug du compilateur) ou des noms de variables étranges comme strongSelf
. Vous pouvez utiliser guard let self = self else { return }
pour déballer weak self
:
class Example {
var closure: (() -> Void)?
init() {
self.closure = { [weak self] in
guard let self = self else {
return
}
// ...
}
}
}
Vous pouvez en savoir plus à ce sujet dans la Proposition d'évolution rapide .