这有什么区别:
_ = navigationController?.popViewController(animated: true)
defer {
let rootVC = navigationController?.topViewController as? RootViewVC
rootVC?.openLink(url: url)
}
return
和此:
_ = navigationController?.popViewController(animated: true)
let rootVC = navigationController?.topViewController as? RootViewVC
rootVC?.openLink(url: url)
return
Apple的快速指南说:“在代码执行离开当前代码块之前,您使用defer语句执行一组语句。 “,但我仍然没有得到它。
答案 0 :(得分:26)
在退货之前,延期声明和声明之间有什么区别?
世界上所有的差异。 1>}语句在返回后执行!这使您可以完成可以通过其他方式完成的事情(我演示here)。
另外,正如已经指出的那样,无论如何退出,都会执行defer
语句。无论你退出当前的范围,它都可以工作,这可能根本不涉及defer
; return
适用于函数体,while块,if结构,do块等。单个defer
不是退出此类范围的唯一方法!您的方法中可能有多个return
,和/或您可能会抛出错误,和/或您可能有return
等等,或者您可能只是到达最后一行范围自然;在每种可能的情况下执行break
。 “手动”编写相同的代码,以便涵盖每个可能的退出,可能非常容易出错。
答案 1 :(得分:14)
在你的例子中实际上没有区别,但请看这个:
func foo(url: URL) -> Int
let fileDescriptor : CInt = open(url.path, O_EVTONLY);
defer {
close(fileDescriptor)
}
guard let bar = something1() else { return 1 }
guard let baz = something2() else { return 2 }
doSomethingElse(bar, baz)
return 3
}
无论函数返回哪一行,都始终执行 close(fileDescriptor)
。
答案 2 :(得分:7)
defer语句用于在执行离开最近范围之前执行一段代码。
例如:
func defer() {
print("Beginning")
var value: String?
defer {
if let v = value {
print("Ending execution of \(v)")
}
}
value = "defer function"
print("Ending")
}
将打印的第一行是:开始
将打印的第二行是:结束
最后一行将打印:结束执行延期功能。
答案 3 :(得分:4)
使用defer
可以避免在函数结束时进行条件清理。
考虑这个例子:
class Demo {
var a : String
init(_ a:String) {
self.a = a
}
func finish() {
print("Finishing \(a)")
}
}
func play(_ n:Int) {
let x = Demo("x")
defer { x.finish() }
if (n < 2) {return}
let y = Demo("y")
defer { y.finish() }
if (n < 3) {return}
let z = Demo("z")
defer { z.finish() }
}
play(1)
play(2)
play(3)
函数play
根据其参数创建一个,两个或三个Demo
个对象,并在运行结束时调用它们finish
。如果函数从中间返回,则defer
语句不会被执行,并且不会为永远不会创建的对象调用finish
。
替代方案需要使用选项:
func play(_ n:Int) {
var x:Demo? = nil
var y:Demo? = nil
var z:Demo? = nil
x = Demo("x")
if (n >= 2) {
y = Demo("y")
}
if (n >= 3) {
z = Demo("z")
}
x?.finish()
y?.finish()
z?.finish()
}
此方法将所有声明放在顶部,并强制您稍后打开选项。另一方面,带有defer
的代码允许您在执行初始化的代码附近编写清理代码。
答案 4 :(得分:-1)
this.context
使用 defer 编写一个代码块,该代码块在函数中的所有其他代码之后,就在函数返回之前执行。无论函数是否引发错误,都将执行代码。即使需要在不同的时间执行设置,您也可以使用defer彼此相邻地编写设置和清除代码。