Как "усилить" опциональную функцию самозащиты в Swift 2.0

Здесь есть аналогичный вопрос о том, как weakify/strongify self, на который отвечает, но мне интересно, как использовать "я" без права -drifting, вызванный 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) }

Ответы

Ответ 1

Вы можете затенять 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. }

Ответ 2

Потому что guard let `self` = self является ошибкой компилятора, как указано Крисом Латтнером. Я попытался бы избежать этого. В вашем примере вы можете использовать простое дополнительное связывание:

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
    }
}

или вы можете создать частный метод

{ [weak self] in
    self?.doSomethingMoreComplicated()
}

...

private func doSomethingMoreComplicated() {
    // Do something more complicated
}