В показанном примере явного retain cycle нет: process не захватывает self и не хранит completion в DataProcessor. Объект может освободиться после handler = nil.
Обнаружение и устранение утечек памяти в асинхронных Swift‑операциях
В показанном примере явного retain cycle нет: process не захватывает self и не хранит completion в DataProcessor. Объект может освободиться после handler = nil.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Задача состоит в том, чтобы проанализировать приведённый асинхронный Swift‑код, выявить места, где возможны утечки памяти, и внести исправления, обеспечив корректное освобождение ресурсов.
class DataProcessor {
func process(data: String, completion: @escaping (String) -> Void) {
DispatchQueue.global().async {
let result = data.uppercased()
DispatchQueue.main.async {
completion(result)
}
}
}
}
var handler: DataProcessor? = DataProcessor()
handler?.process(data: "hello") { result in
print(result)
handler = nil // освобождаем объект после использования
}
В данном примере необходимо обратить внимание на захват self (или переменной‑обработчика) внутри замыкания и гарантировать, что после выполнения операции объект будет корректно деинициализирован, чтобы не оставлять висящих ссылок в памяти.
Ответ
В показанном примере явного retain cycle нет: process не захватывает self и не хранит completion в DataProcessor. Объект может освободиться после handler = nil.
Очереди временно удерживают замыкания и data/result до выполнения. Completion обращается к внешней переменной handler, но сам DataProcessor не удерживает этот completion обратной ссылкой, поэтому кольцо владения не образуется. Добавлять [weak self] в метод, где self не используется, бессмысленно. Настоящие риски — завершение процесса до callback, конкурентное изменение общей переменной и отсутствие отмены при расширении задачи. Утечку нужно подтверждать графом ссылок, а не наличием любого escaping-замыкания.