同様の質問weakify
/strongify
selfの方法について回答がありますが、これにより、右方向にドリフトすることなく "self"を使用する方法について疑問に思っています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) }
あなたcan影self
; 「何をしているか知っている」ことを示すバックティックが必要なだけです。例えば:
foo.doSomethingAsyncWithBar(bar) { [weak self] result in
guard let `self` = self else { return }
self.receivedResult(result)
}
または、あなたの例では:
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. }
Swift 4.2なので、次の構文を使用できます。
{ [weak self] in
guard let self = self else { return }
// self is not an optional anymore, it is held strongly
}
詳細については、Swift進化の提案 SE-0079 を参照してください。
guard let
を使用する以外のアプローチも役立つ場合があります(たとえば、短くしたり、読みやすくしたりできます)。次のセクションも参照してください。いくつかの例では、strongSelf
をself
に置き換えるだけです。
guard let `self` = self
は Chris Lattnerが述べたコンパイラのバグ なので、私はそれを避けようとします。あなたの例では、単純なオプションのチェーンを使用できます:
return { [weak self] in
self?.doSomethingNonOptionalSelf()
}
場合によっては、パラメーターとしてselfを使用する必要があります。このような場合、flatMap
を使用できます(オプションの型に対して):
{ [weak self] in
self.flatMap { $0.delegate?.tableView($0, didSelectRowAt: indexPath) }
}
より複雑なことを行う必要がある場合は、if let
構文を使用できます。
{ [weak self] in
if let strongSelf = self {
// Do something more complicated using strongSelf
}
}
またはguard let
構成:
{ [weak self] in
guard let strongSelf = self else { return }
// Do something more complicated using strongSelf
}
または、プライベートメソッドを作成できます。
{ [weak self] in
self?.doSomethingMoreComplicated()
}
...
private func doSomethingMoreComplicated() {
// Do something more complicated
}
Swift 4.2以降、バックティック(コンパイラのバグ)やstrongSelf
のような奇妙な変数名を使用する必要がなくなりました。guard let self = self else { return }
を使用して、weak self
:
class Example {
var closure: (() -> Void)?
init() {
self.closure = { [weak self] in
guard let self = self else {
return
}
// ...
}
}
}
詳細については、 Swiftの進化の提案 を参照してください。