Вам нужно будет понять идею переменного захвата замыкания.
Рассмотрим этот пример:
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"
Capture List сохраняет неизменяемую копию переменных. Благодаря этой копии дальнейшие изменения в калькуляторе вне замыкания не повлияют на замыкание.
Вы можете захватывать несколько переменных одновременно, поэтому это называется Список захвата. Пример:
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"
person
nayem
schedule
05.04.2018