Sobes.tech
Middle

Обяснете разликата между escaping и non-escaping closures и в кои случаи е необходимо да използвате @escaping.

sobes.tech AI

Отговор от AI

По подразбиране, затварящите се блокове са non-escaping.

Non-escaping затваряне:

  • Изпълнява се в тялото на функцията, към която се предава.
  • Засмуква променливи, но ги освобождава след приключване на функцията.
  • Не оцеляват функцията.
func doSomething(completion: () -> Void) {
    // Викаме completion тук
    completion() 
}

Escaping затваряне:

  • Изпълнява се след връщането от функцията, към която се предава.
  • Оцеляват след тялото на функцията.
  • Могат да бъдат запазени за по-късно изпълнение, например в друг поток или асинхронно.
  • Засмуква променливи, запазвайки силни препратки, което може да доведе до цикли на силни препратки (retain cycles). Изисква явна декларация @escaping.
class DataManager {
    var completionHandlers: [() -> Void] = []

    func addCompletionHandler(handler: @escaping () -> Void) {
        completionHandlers.append(handler)
    }

    func performTasks() {
        // Изпълнение на задачи...
        for handler in completionHandlers {
            handler() // По-късно извикване
        }
    }
}

Използването на @escaping е необходимо в следните случаи:

  • Когато затварянето се запазва като свойство на клас или структура.
  • Когато затварянето се предава към друг поток или асинхронна операция (например, мрежов заявка, GCD, OperationQueue).
  • Когато затварянето се използва като обработчик на събития или делегат.