Блокировать блокировки в Swift?

Традиционно в Objc мы делаем weakSelf для предотвращения дополнительного количества удержания для блоков.

Как быстро выполнять внутренние циклы сохранения, которые происходят в блоках для Objc?

Ответ 1

Чтобы блок не содержал значительную ссылку на объект, вы должны определить список захвата для блока.

Синтаксис выражения закрытия определяется следующим образом:

{ ( /*parameters*/ ) -> /*return type*/ in

    // statements
}

Но это более подробно описано в документации для включения списка захвата. Это фактически эквивалентно синтаксису выражения, определяемому следующим образом:

{ [ /*reference type*/ /*object*/, ... ] ( /*parameters*/ ) -> /*return type*/ in

    // statements
}

... где /*reference type*/ может быть либо weak, либо unowned.

Список захвата - это первое, что появляется в закрытии, и оно необязательно. Синтаксис, как показано выше, определяется как одна или несколько пар ссылочного типа, за которыми следует объект; каждая пара разделяется запятой. Например:

[unowned self, weak otherObject]

Полный пример:

var myClosure = {
    [unowned self] in
    print(self.description)
}

Обратите внимание, что ссылка unowned не является необязательной, поэтому ее не нужно разворачивать.

Надеюсь, это ответит на ваш вопрос. Вы можете прочитать больше о ARC в Swift в соответствующем разделе documentation.

Вы должны обратить особое внимание на разницу между weak и unowned. В вашей реализации может быть безопаснее использовать weak, поскольку использование unowned предполагает, что объект никогда не будет равен нулю. Это может привести к сбою вашего приложения, если объект фактически был освобожден до использования в вашем закрытии.

Используя weak в качестве ссылочного типа, вы должны развернуть с помощью ? следующим образом:

var myClosure = {
    [weak self] in
    print(self?.description)
}

Ответ 2

Единственное, что отбросило меня с помощью списков захвата, было тогда, когда нужно использовать слабый vs unowned.

Книга переделала эти правила:

Если self может быть nil в использовании замыкания [слабый я].

Если self никогда не будет nil в использовании закрытия [unowned self].

В разделе "Книга быстрого языка программирования" см. раздел "Слабые и неопубликованные ссылки" .

Ответ 3

Как описано выше, существует 2 возможности избежать циклов удержания в Swift, и это weak и unowned, как описано ниже:

var sampleClosure = { [unowned self] in
    self.doSomething()
}

где self никогда не может быть nil.

var sampleClosure = { [weak self] in
    self?.doSomething()
}

где self необходимо развернуть с помощью ?. Здесь есть важное замечание, если есть больше инструкций, которые используют self и могут делиться результатами и т.д., Возможно правильный способ:

var sampleClosure = { [weak self] in
    if let this = self{
       this.doSomething()
       this.doOtherThings()
    }             
}

или

var sampleClosure = { [weak self] in
    guard let strongSelf = self else{
       return
    }
    strongSelf.doSomething()
    strongSelf.doOtherThings()             
}