函数延迟在Swift 2.0中不起作用

时间:2016-01-20 08:44:54

标签: ios xcode swift swift-playground

我在Playground中测试Swift 2.0和新关键字defer

func branch() -> String {

    var str = ""

    defer { str += "xxx" }
    str += "1"

    let counter = 3;

    if counter > 0 {
        str += "2"
        defer { str += "yyy" }
        str += "3"
    }      
    str += "4"

    return str    
}

let bran = branch()

我希望bran"123yyy4xxx",但实际上是"123yyy4"

为什么我推迟(str += "xxx")无法按预期工作?

3 个答案:

答案 0 :(得分:7)

  

延迟语句推迟执行,直到退出当前范围。

苹果说的话。所以defer语句将在return语句之后执行。这就是为什么你看不到预期结果的原因。

答案 1 :(得分:7)

Greg是正确的,如果你想用你的代码获得相同的结果,那么你可以这样做:

var str = ""

func branch() {

    str = ""
    defer { str += "xxx" }
    str += "1"


    let counter = 3

    if counter > 0 {
        str += "2"
        defer { str += "yyy" }
        str += "3"
    }
    str += "4"

}

branch()
str    //"123yyy4xxx"

答案 2 :(得分:5)

首先:defer被执行,因为您可以清楚地看到向其添加print(str)

现在解释为什么返回值不反映更改的值:
这样做的原因是String是不可变的 - 每当您编写str += something时,您都会创建一个全新的String实例并将其存储在str内。

如果您编写return str,则会返回str的当前实例123yyy4。然后调用defer并将全新且无关的String 123yyy4xxx分配给str。但这不会改变String中存储的先前str对象,它只会覆盖它,因此不会影响已经“发生”的return

如果您更改方法以使用NSMutableString,则您将始终使用相同的实例,因此结果将正确输出123yyy4xxx

func branch() -> NSMutableString {
    var str = NSMutableString()
    defer { str.appendString("xxx") }
    str.appendString("1")
    let counter = 3;
    if counter > 0 {
        str.appendString("2")
        defer { str.appendString("yyy") }
        str.appendString("3")
    }
    str.appendString("4")
    return str
}


let bran1 = branch()

在该代码中,返回返回存储在str中的实例,并且延迟更改实例,它不会分配新实例,但会更改已存在的实例。

为了便于解释,您可以尝试在不同阶段查看str的内存地址:

  • return
  • 在更改str
  • 中的defer之前
  • 更改后

对于NSMutableString,所有三种情况都会产生相同的内存地址,这意味着实例保持不变。然而,String打印两个不同的内存地址,导致返回的String指向someAddress,延迟的指向someOtherAddress