Что на самом деле использовать не экранирующие замыкания? - PullRequest
2 голосов
/ 17 февраля 2020

Если функция может возвращать само значение, тогда зачем вызывать не экранирующее закрытие для возврата значения? Рассмотрим следующий пример

 func add(a: Int, b: Int, completion: (Int) -> ()) {
        let addition = a + b
        completion(addition)
 }

Ответы [ 2 ]

2 голосов
/ 17 февраля 2020

Типичные случаи использования для закрытия:

  1. Асинхронные вызовы; работа в сети.

  2. Функции хранятся в виде переменных; продумайте действия и предоставленные обратные вызовы.

  3. Планирование задач в очереди отправки.

Если есть процесс, для выполнения которого требуется некоторое время, чтобы выполнить работу и вернуть результат. В этих случаях закрытием являются лучшие варианты.

Не выходящие замыкания

Не выходящие замыкания имеют очень четкий жизненный цикл и стали типом замыкания по умолчанию в Swift 3 благодаря этому. Невыкрывающееся замыкание простое: оно передается в функцию (или другую, содержащую область), функция / область выполняет это замыкание, и функция возвращается. Закрытие не может вернуться или завершиться после выполнения тела вызывающей функции. В связи с этим компилятор может оптимизировать не-экранирующие замыкания по экранирующим замыканиям.

Поведение по умолчанию при закрытии (без экранирования)

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

func macICanBuy(budget: Int, closure: (String) -> Void) {
  print("checking budget...")

  closure("Mcdonalds' Big Mac")

  print("macICanBuy finished execution")
}

override func viewDidLoad(){
  macICanBuy(budget: 100, closure: { mac in
    print("I can afford a \(mac)")
  })
}

// output: 
// checking budget...
// I can afford a Mcdonalds' Big Mac
// macICanBuy finished execution

Прежде чем приложение выполнит функцию macICanBuy, оно загрузит переданный параметр (бюджет и закрытие) в память телефона (RAM), чтобы функция могла использовать эти данные.

После того, как приложение завершит выполнение sh функции macICanBuy, приложению больше не нужны данные о бюджете и закрытии, поэтому оно удалит их из памяти. Данные замыкания не сумели избежать удаления из памяти после завершения выполнения функции, поэтому они называются «неэкранирующими» замыканиями.

Выше ссылка из:

https://fluffy.es/what-is-escaping-closure/

1 голос
/ 17 февраля 2020

Например, параметры a и b по некоторым причинам должны быть положительными числами. Есть 3 способа обойти это дело:

1) Вы можете добавить эту проверку в функцию, которая вызывает add. Если вы сделаете это, вы повторите этот код в любое время до add вызова. Это плохая идея из-за дублирования кода; 2) Вы можете добавить эту проверку в методе add и вернуть ошибку закрытию. В любом закрытии вы должны обработать эту ошибку, даже если вы не хотите выполнять какой-либо код в этом случае. Так что это тоже не очень хорошая идея; 3) Вы можете добавить эту проверку в метод add и вернуть логическое значение, показывающее правильность параметров. Если параметры верны, вы вычисляете результат и вызываете замыкание, как в этом коде:

func add(a: Int, b: Int, completion: (Int) -> ()) -> Bool {
    guard a > 0, b > 0 else {
      return false
    }

    let addition = a + b
    completion(addition)

    return true
}

if !add(a: someA, b: someB, completion: {sum in print(sum)}) {
  print("Wrong numbers!")
}
...