web-dev-qa-db-ja.com

Swift 2.0でガードを使用してオプションの自己を「強化」する方法

同様の質問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) }
27
Brian Gerstle

あなたcanself; 「何をしているか知っている」ことを示すバックティックが必要なだけです。例えば:

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. }
37
Jason

Swift 4.2

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を使用する以外のアプローチも役立つ場合があります(たとえば、短くしたり、読みやすくしたりできます)。次のセクションも参照してください。いくつかの例では、strongSelfselfに置き換えるだけです。

Swift 4.1およびそれ以前

guard let `self` = selfChris 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
}
25
Marián Černý

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の進化の提案 を参照してください。

6
Amer Hukic