Используя defer
, невозможно напрямую отложить что-либо, что произойдет за пределами текущей области, например условия if
, в котором вы находитесь. Однако можно отложить что-то безоговорочно и переместите условие в defer
:
defer {
if object.isOpen { object.close() }
}
Более общее решение в этом направлении будет выглядеть примерно так:
var deferred: (() -> Void)? = nil
defer { deferred?() }
if object.isOpen {
deferred = { object.close() }
}
Это более общее решение позволило бы отложить разные вещи на основе разных условий, но, очевидно, самое большее по одному за раз. Для поддержки более чем одного вы, конечно, можете использовать массив:
var deferred = [(() -> Void)]()
defer {
for f in deferred.reversed() { f() }
}
if object1.isOpen {
deferred.append { object1.close() }
}
if object2.isOpen {
deferred.append { object2.close() }
}
Однако я настоятельно не рекомендую это , поскольку оно запутывает поток кода и, по-видимому, свидетельствует о плохом дизайне в других местах. Обычно причина использования defer
заключается в том, что у вас есть несколько выходов из области действия и вы хотите избежать копирования всех одинаковых кодов очистки, но здесь у вас есть несколько путей очистки. Я бы попытался выделить пути, ведущие к различным требованиям очистки.