这是什么之间的区别:
_ = 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
苹果的迅速方针说:“你使用defer语句执行代码离开当前代码块之前执行一组语句。 ”,但我还是不太明白。
什么是正确的只是返回前defer语句和语句之间的区别?
在世界上所有的差异。该defer
语句返回后执行!这使您可以完成的事情,可以在没有其他办法来实现。
例如,你可以返回一个值,然后更改值。苹果利用这一招相当有规律;这里,例如,是从示出了如何编写自定义序列的序列文档代码:
struct Countdown: Sequence, IteratorProtocol {
var count: Int
mutating func next() -> Int? {
if count == 0 {
return nil
} else {
defer { count -= 1 }
return count
}
}
}
如果你写的是
count -= 1
return count
...这将打破;我们不想递减count
,然后返回它,我们要返回count
,然后递减它。
此外,由于已经被指出的那样,defer
语句无论你怎么退出执行。和它的作品无论你退出当前范围,这可能不涉及return
可言; defer
适用于函数体中,而块,如果构建一个DO块,等等。单return
不退出这样一个范围内的唯一途径!有可能是你的方法不止一个return
,和/或你可能会抛出一个错误,和/或你可能有一个break
,等等,等等,或者你可能只是达到自然范围的最后一行;该defer
在一切可能的情况下执行。编写相同的代码“手动”,以涵盖所有可能的退出,可以很容易出错。
在您的例子其实没有什么区别,但是请看看这个:
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)
始终执行无论在哪个行的函数返回。
defer语句用来执行离去最近正好范围之前执行一段代码。
例如:
func defer() {
print("Beginning")
var value: String?
defer {
if let v = value {
print("Ending execution of \(v)")
}
}
value = "defer function"
print("Ending")
}
这将打印第一行是:起点
第二线,将打印的是:结束
最后一行将打印为:结束延迟功能的执行。
使用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
的代码,而另一方面,让你写的清理代码,不会初始化代码的旁边。