Я анимирую оставшееся время для некоторых сцен в моем приложении. У меня проблема в том, что когда пользователь прерывает эту сцену, переходя к следующей сцене, анимация не останавливается
Этот код является упрощенной версией происходящего:
struct ContentView: View {
@State private var remaining: Int = 40
@State private var sceneIndex: Int = 0
var body: some View {
VStack(spacing: 30) {
Text("Remaining:")
EmptyView().modifier(DoubleModifier(value: remaining))
Button(action: {
self.sceneIndex += 1
if self.sceneIndex == 1 {
withAnimation(.linear(duration: 10)) {
self.remaining = 30
}
} else {
withAnimation(.linear(duration: 0)) {
self.remaining = 30 // changing this to any other value will stop the animation
}
}
}) {
Text("Go to next scene")
}
}
}
}
struct DoubleModifier: AnimatableModifier {
private var value: Double
init(value: Int) {
self.value = Double(value)
}
var animatableData: Double {
get { value }
set { value = newValue }
}
func body(content: Content) -> some View {
Text("\(Int(value)) seconds remaining")
}
}
То, что происходит, - то, что, когда пользователь щелкает, анимация обратного отсчета инициализируется с продолжительностью 10 секунд и устанавливает оставшееся время от 40 до 30 секунд. Теперь, когда пользователь нажимает кнопку пропуска, анимация должна остановиться и go до оставшихся 30 секунд. Тем не менее, он по-прежнему показывает анимацию от 40 до 30 (где-то посередине).
Если я изменю self.remaining на 30 в операторе else, значение не обновляется, поскольку оно уже установлено на 30, но внутренне это все еще оживляет. Если я изменю self.remaining на любое другое допустимое значение, кроме 30, например self.remaining = 29, анимация действительно немедленно остановится.
Я мог бы заменить содержимое в выражении else на:
withAnimation(.linear(duration: 0)) {
self.remaining = 29
DispatchQueue.main.async {
self.remaining = 30
}
}
, который работает, но чувствует себя очень грязно, и в моем случае не всегда возможно использовать DispatchQueue.main.asyn c
Есть ли другой, лучший способ остановить анимацию и пропустить к месту назначения?
Возможно ли каким-то образом присвоить некоторый идентификатор идентификатору self.remaining = 30 в операторе else так, чтобы swiftUI знал, что значение действительно изменилось, хотя на самом деле это не произошло, так что swiftUI останавливает анимацию