在退货之前,延期声明和声明之间的区别是什么?

时间:2017-02-28 15:43:39

标签: ios swift deferred

这有什么区别:

_ = 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语句执行一组语句。 “,但我仍然没有得到它。

5 个答案:

答案 0 :(得分:26)

  

在退货之前,延期声明和声明之间有什么区别?

世界上所有的差异。 }语句在返回后执行!这使您可以完成可以通过其他方式完成的事情(我演示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彼此相邻地编写设置和清除代码。