发布于 2015-06-14 01:53:29 | 173 次阅读 | 评论: 0 | 来源: 网络整理

捕获值(Capturing Values)

闭包可以在其定义的上下文中捕获常量或变量。 即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。

Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数。 嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量。

下例为一个叫做makeIncrementor的函数,其包含了一个叫做incrementor嵌套函数。 嵌套函数incrementor从上下文中捕获了两个值,runningTotalamount。 之后makeIncrementorincrementor作为闭包返回。 每次调用incrementor时,其会以amount作为增量增加runningTotal的值。


func makeIncrementor(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}

makeIncrementor返回类型为() -> Int。 这意味着其返回的是一个函数,而不是一个简单类型值。 该函数在每次调用时不接受参数只返回一个Int类型的值。 关于函数返回其他函数的内容,请查看函数类型作为返回类型

makeIncrementor函数定义了一个整型变量runningTotal(初始为0) 用来存储当前跑步总数。 该值通过incrementor返回。

makeIncrementor有一个Int类型的参数,其外部命名为forIncrement, 内部命名为amount,表示每次incrementor被调用时runningTotal将要增加的量。

incrementor函数用来执行实际的增加操作。 该函数简单地使runningTotal增加amount,并将其返回。

如果我们单独看这个函数,会发现看上去不同寻常:


func incrementor() -> Int {
    runningTotal += amount
    return runningTotal
}

incrementor函数并没有获取任何参数,但是在函数体内访问了runningTotalamount变量。这是因为其通过捕获在包含它的函数体内已经存在的runningTotalamount变量而实现。

由于没有修改amount变量,incrementor实际上捕获并存储了该变量的一个副本,而该副本随着incrementor一同被存储。

然而,因为每次调用该函数的时候都会修改runningTotal的值,incrementor捕获了当前runningTotal变量的引用,而不是仅仅复制该变量的初始值。捕获一个引用保证了当makeIncrementor结束时候并不会消失,也保证了当下一次执行incrementor函数时,runningTotal可以继续增加。


注意:
Swift 会决定捕获引用还是拷贝值。
您不需要标注amount或者runningTotal来声明在嵌入的incrementor函数中的使用方式。
Swift 同时也处理runingTotal变量的内存管理操作,如果不再被incrementor函数使用,则会被清除。
 

下面代码为一个使用makeIncrementor的例子:


let incrementByTen = makeIncrementor(forIncrement: 10)

该例子定义了一个叫做incrementByTen的常量,该常量指向一个每次调用会加10的incrementor函数。 调用这个函数多次可以得到以下结果:


incrementByTen()
// 返回的值为10
incrementByTen()
// 返回的值为20
incrementByTen()
// 返回的值为30

如果您创建了另一个incrementor,其会有一个属于自己的独立的runningTotal变量的引用。 下面的例子中,incrementBySevne捕获了一个新的runningTotal变量,该变量和incrementByTen中捕获的变量没有任何联系:


let incrementBySeven = makeIncrementor(forIncrement: 7)
incrementBySeven()
// 返回的值为7
incrementByTen()
// 返回的值为40


注意:
如果您将闭包赋值给一个类实例的属性,并且该闭包通过指向该实例或其成员来捕获了该实例,您将创建一个在闭包和实例间的强引用环。
Swift 使用捕获列表来打破这种强引用环。更多信息,请参考 闭包引起的循环强引用
 

最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务