繁体   English   中英

用括号输入Swift中闭包的参数

[英]Input parameter to closure in Swift with brackets

我将在RxSwiftRxSwift以下教程:

http://adamborek.com/thinking-rxswift/

并且无法理解以下模式:

           searchBar.rx.text.orEmpty
------------> .flatMap { [spotifyClient] query in
                   return spotifyClient.rx.search(query: query)
             }.map { tracks in
                   return tracks.map(TrackRenderable.init)
             }

这个方括号输入参数: [spotifyClient] query对我来说似乎很奇怪。 我查看官方Apple文档中的闭包和函数,我看不到这些输入参数的任何示例。 Objective C这不会让我感到烦恼,但它是Swift 谁能解释一下,这个参数在这里意味着什么?

您需要了解闭包概念的变量捕获

考虑这个例子:

struct Calculator {
    var a: Int
    var b: Int

    var sum: Int {
        return a + b
    }
}

然后你用它作为:

let calculator = Calculator(a: 3, b: 5)

// You define a closure where you will use this calculator instance
let closure = {
    // closure captures the variables that are declared prior to the declaration of the closure.
    // your calculator instance is being captured here
    // it's default variable capture
    print("The result is \(calculator.sum)")
}

closure() // Prints "The result is 8"

直到现在,一切都还好。 你得到了预期的结果。

现在考虑将计算器实例声明为var因为在某些时候你需要改变它的状态。 这就是出现复杂性的情况。 看:

var calculator = Calculator(a: 3, b: 5)

let closure = {
    print("The result is \(calculator.sum)")
}

// You change the state of your calculator instance anytime before the closure gets executed
calculator.b = 20
// When the closure actually executes, you will be affected by any changes outside the closure 
closure() // Prints "The result is 23"

因此, 默认变量捕获并不能真正帮助您,而是在您的情况下创建问题。


如果你想阻止这种行为并打印8,即使属性在闭包内捕获后发生变化,我们也可以使用如下捕获列表显式捕获变量:

// [calculator] is your capture list
let closure = { [calculator] in
    print("The result is \(calculator.sum)")
}
// change anything with calculator instance
calculator.b = 20
// execute the closure
closure() // Prints "The result is 8"

捕获列表保留变量的不可变副本。 由于这个副本,在闭包之外对计算器的进一步更改不会影响关闭。

您可以一次捕获多个变量,因此称为捕获列表 例:

let closure = { [variable1, variable2, variable3] in
    print(variable1)
    print(variable2)
    print(variable3)
}

我建议你阅读这篇文章在Swift Closures中捕获值



现在,在您的情况下, spotifyClient是一个可能负责进行API调用的类的实例。 此实例可能需要进行一些更改以调用不同的API。 因此,为了防止对此闭包外的spotifyClient进行任何更改的影响,您可以在捕获列表中捕获此实例。



捕获列表与参数列表:

您将参数列表与捕获列表混淆。 通用语法是:

{ [capture list] (parameter list) in
    ...
    ...
}

现在来看看上面例子的修改版本:

let closure: (String)-> Void = { [calculator] stringParameter in // When using single parameter, you can always omit the () parentheses
    print("\(stringParameter). The result is \(calculator.sum)")
}

// change anything with calculator instance
calculator.b = 20
// execute the closure
closure("Hey") // Prints "Hey. The result is 8"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM