我将在RxSwift
上阅读以下教程:
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
。谁能解释一下,这个参数在这里意味着什么?
答案 0 :(得分:9)
您需要了解 变量捕获关闭 的想法。
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)
}
我建议你阅读这篇文章Capturing Values In 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"