2017-02-28 94 views
5

這是什麼之間的區別:和延遲陳述與陳述在退貨前的區別是什麼?

_ = 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語句執行代碼離開當前塊之前執行一組語句的代碼。 「,但我還是不太明白。

回答

9

延遲陳述和返回前的陳述權有什麼區別?

世界上所有的差異。 defer聲明執行返回!這可以讓你完成以其他方式完成的事情(如我演示here)。

此外,正如已經指出的那樣,defer語句被執行,不管如何您退出。無論您退出當前的範圍,它可能根本不涉及return; defer適用於函數體,while塊,if構造,do塊等。一個return不是退出此範圍的唯一方法!在你的方法中可能有多個return,和/或你可能會拋出一個錯誤,和/或你可能有一個break等,或者你可能自然地到達該範圍的最後一行; defer在每種情況下都會執行。 「手工編寫」相同的代碼,以覆蓋每個可能的退出,可能非常容易出錯。

+3

是否確定推遲語句在返回後執行? Swift編程語言指導書說:「在函數返回前,使用延遲寫入在函數中的所有其他代碼之後執行的代碼塊」。它在函數返回前說「 –

+0

試過在操場上運行,推遲聲明在返回後不被調用 – Rana

7

在你的榜樣其實沒有什麼區別,但是請看看這個:

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)始終執行不管哪一行函數返回。

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的代碼可讓您在執行初始化的代碼附近編寫清理代碼。

2

defer語句用於在執行離開最近的作用域之前執行一段代碼。

例如:

func defer() { 
print("Beginning") 
var value: String? 
defer { 
    if let v = value { 
     print("Ending execution of \(v)") 
    } 
} 
value = "defer function" 
print("Ending") 
} 

第一線,將打印爲:開始

第二行,它將打印的是:結束

最後一行將打印爲:中結束執行推遲功能。