У меня есть следующая функция, которая ведет себя не так, как я ожидал.
func dispatchTrouble(startValue:Float, endValue:Float, duration:Float)
{
//100 increment steps per second
let incrementSteps = duration * 100
for(var step = 0.0 as Float; step < incrementSteps; step++)
{
var delayInSeconds = step * (duration / incrementSteps)
let answer = Float(NSEC_PER_SEC) * delayInSeconds
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(answer))
println(step)
//Using GCD to perform this on the main thread.
dispatch_after(popTime, dispatch_get_main_queue()){
println(step)
let fraction = step / incrementSteps
let incrementedValue = startValue + (endValue - startValue) * fraction
println(incrementedValue)
}
}
}
Я ожидал, что оператор println(incrementedValue) будет отображать значение, которое увеличивается от startValue до endValue и завершается в течение количества секунд, прошедших в продолжительности.
Однако поведение, которое я получаю, заключается в том, что код в закрытии dispatch_after печатает только окончательное значение, он никогда не печатает приращения.
Задержка происходит, как и ожидалось, но все значения рассчитываются так, как если бы цикл for уже завершился. Первый println(step) показывает увеличение шага, а второй показывает только конечное значение.
Я явно неправильно понимаю, как это должно работать. Я ожидал, что код в замыкании будет содержать значения, существовавшие на момент вызова метода dispatch_after, но вместо этого он действует так, как будто использует то значение, которое было на момент фактического выполнения.
Как я могу захватить значения на каждой итерации цикла for и выполнить код в закрытии, используя это?
step
попадает в коробку - скорее всего, потому чтоprintln()
в лямбда-выражении принимает объект. Помните, компилятор не может знать, чтоprintln()
не изменяетstep
. Я предполагаю, что альтернатива использованию неизменной копии по значению при захвате привела бы к столь же удивительным результатам... 22.03.2015println
никогда не сможет изменить шаг 22.03.2015