简体   繁体   English

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

[英]Input parameter to closure in Swift with brackets

I am going through the following tutorial on RxSwift : 我将在RxSwiftRxSwift以下教程:

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

and having trouble understanding the following pattern: 并且无法理解以下模式:

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

This square brackets input parameter: [spotifyClient] query seems very weird for me. 这个方括号输入参数: [spotifyClient] query对我来说似乎很奇怪。 I looked over official Apple documentation for closures and functions and I can not see any examples of such input parameters. 我查看官方Apple文档中的闭包和函数,我看不到这些输入参数的任何示例。 In Objective C this would not bother me much, but it is Swift . Objective C这不会让我感到烦恼,但它是Swift Could anyone explain, what this parameter means here? 谁能解释一下,这个参数在这里意味着什么?

You will need to understand the variable capturing of closure idea. 您需要了解闭包概念的变量捕获

Consider this example: 考虑这个例子:

struct Calculator {
    var a: Int
    var b: Int

    var sum: Int {
        return a + b
    }
}

Then you use this as: 然后你用它作为:

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"

Till now, everything is okay. 直到现在,一切都还好。 You get what's expected. 你得到了预期的结果。

Now consider you declare the calculator instance as var because in some point you need to mutate it's state. 现在考虑将计算器实例声明为var因为在某些时候你需要改变它的状态。 This is the case where complexity arises. 这就是出现复杂性的情况。 Look: 看:

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"

So, the default variable capture isn't really helping you, instead it's creating problem in your case. 因此, 默认变量捕获并不能真正帮助您,而是在您的情况下创建问题。


If you want to prevent this behaviour and print 8 even if the properties change after their capturing inside the closure, we can explicitly capture the variable with a capture list like this: 如果你想阻止这种行为并打印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"

Capture List keeps immutable copy of the variable(s). 捕获列表保留变量的不可变副本。 Thanks to this copy, further changes to calculator, outside the closure, will not affect the closure. 由于这个副本,在闭包之外对计算器的进一步更改不会影响关闭。

You can capture multiple variables at once, hence it's called Capture List . 您可以一次捕获多个变量,因此称为捕获列表 Example: 例:

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

I recommend you read this article Capturing Values In Swift Closures . 我建议你阅读这篇文章在Swift Closures中捕获值



Now, in your case spotifyClient is an instance of a class that may be responsible to make API calls. 现在,在您的情况下, spotifyClient是一个可能负责进行API调用的类的实例。 This instance may need some changes for calling different APIs. 此实例可能需要进行一些更改以调用不同的API。 So, to prevent the affect of any changes to spotifyClient outside this closure you capture this instance in a Capture List . 因此,为了防止对此闭包外的spotifyClient进行任何更改的影响,您可以在捕获列表中捕获此实例。



Capture List vs. Parameter List: 捕获列表与参数列表:

You are confusing the parameter list with the capture list. 您将参数列表与捕获列表混淆。 The generic syntax is: 通用语法是:

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

Now take a look at the modified version of the above example: 现在来看看上面例子的修改版本:

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