Список захвата быстрого закрытия с нулевыми значениями - PullRequest
0 голосов
/ 18 октября 2018

Я получаю ссылку на делегат, для которой в конечном итоге задано какое-то значение, но изначально оно равно nil.Тем не менее, захваченная ссылка остается нулевой, даже если делегат установлен.

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { [weak delegate] in
    delegate?.something() // delegate is nil
}

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { [weak self] in
    self?.delegate?.something() // delegate is not nil
}

Что здесь происходит?

1 Ответ

0 голосов
/ 18 октября 2018

Использование списка в будущем, такого как [weak delegate] in, приведет к копированию значения делегата в тот момент, когда закрытие инициализируется.Поэтому, если в этот момент делегат равен nil, если if останется nil внутри замыкания, не важно, измените ли вы self.delegate в более позднее время.Это также верно для [weak self], с небольшим исключением, что self обычно не изменяется в Swift.

Проверьте этот пример:

class Delegate {

}

class A {
    var delegate:Delegate?

    func foo() {
        print ("in foo ---------------------")
        delegate = nil
        print ("delegate before: \(delegate)")  // prints: "nil"
        var closure = { print ("in closure: \(self.delegate)")}
        closure()   // prints: "in closure: nil"
        delegate = Delegate()
        print ("delegate after: \(delegate)") // prints "Optional(SwiftPlayground.Delegate)"
        closure() // prints "in closure: Optional(SwiftPlayground.Delegate)"
    }
    func bar() {
        print ("in bar ---------------------")
        delegate = nil  // prints "nil"
        print ("delegate before: \(delegate)")
        var closure = { [weak delegate] in print ("in closure: \(delegate)")}
        closure() // prints: "in closure: nil"
        delegate = Delegate()   // prints "Optional(SwiftPlayground.Delegate)"
        print ("delegate after: \(delegate)")
        closure() // prints "nil"
    }
}

let a = A()
a.foo()
a.bar()

Здесь самый последний closure() вызов func bar напечатает nil, потому что delegate был nil во время инициализации closure.

...