Swift 破碎的动画快捷界面

Swift 破碎的动画快捷界面,swift,animation,swiftui,Swift,Animation,Swiftui,我最初有这个问题。@arsenius提出的解决方案适用于这个玩具示例。然而,我的应用程序更复杂,我花了很长时间才找到动画的中断点。在本例中,我使用了两个动画HStack。但是如果我用两个不同的(!)自定义视图替换这些HStack,动画将再次中断 代码如下: 类状态:ObservableObject{ @发布的var showSolution=false } 结构ContentView:View{ @EnvironmentObject变量状态:状态 var body:一些观点{ VStack{ i

我最初有这个问题。@arsenius提出的解决方案适用于这个玩具示例。然而,我的应用程序更复杂,我花了很长时间才找到动画的中断点。在本例中,我使用了两个动画
HStack
。但是如果我用两个不同的(!)自定义视图替换这些
HStack
,动画将再次中断

代码如下:

类状态:ObservableObject{
@发布的var showSolution=false
}
结构ContentView:View{
@EnvironmentObject变量状态:状态
var body:一些观点{
VStack{
if state.showSolution{
CustomToggleOne()
.背景(颜色.红色)
.id(“一”)
.animation(animation.default)
.transition(.slide)
}否则{
CustomToggleTwo()
.背景(颜色.黄色)
.id(“两个”)
.animation(animation.default.delay(2))
.transition(.slide)
}
}
}
}
结构CustomToggleOne:视图{
@EnvironmentObject变量状态:状态
var body:一些观点{
HStack{
垫片()
按钮(操作:{
动画片{
self.state.showSolution.toggle()
}
}){
文本(“下一页”)
}.padding()
垫片()
}
}
}
结构CustomToggleTwo:视图{
@EnvironmentObject变量状态:状态
var body:一些观点{
HStack{
垫片()
按钮(操作:{
动画片{
self.state.showSolution.toggle()
}
}){
文本(“下一页”)
}.padding()
垫片()
}
}
}
我在
SceneDelegate.swift
的ContentView中添加了一个
State
实例,作为
EnvironmentObject
,如下所示:

let contentView=contentView().environment(\.managedObjectContext,context).environmentObject(State())

当我们在
ContentView
中两次使用
CustomToggleOne()
而不是
CustomToggleTwo()
时,可以看到预期的动画。以下是正确的方法,以及下面和注释中的一些解释。使用Xcode 11.2/iOS 13.2进行测试

提醒:不要在预览中测试转换-仅在模拟器或设备上

// !! Don't name your types as API,
// State is SwiftUI type, might got unpredictable weird issues
class SolutionState:ObservableObject{
    @Published var showSolution = false
}

struct TestBrokenAnimation: View {
    @EnvironmentObject var state:SolutionState

    var body:some View {
        VStack {
            if state.showSolution{
                CustomToggleOne()
                    .background(Color.red)
                    .id("one")
                    .transition(.slide) // implicit animations confuse transition, don't use it
            } else {
                CustomToggleTwo()
                    .background(Color.yellow)
                    .id("two")
                    .transition(.slide)
            }
        }
    }
}
public func withAnimation<Result>(_ animation: Animation? = .default, 
              _ body: () throws -> Result) rethrows -> Result
struct CustomToggleOne: View{
    @EnvironmentObject var state:SolutionState

    var body:some View{
        HStack{
            Spacer()
            Button(action:{
                withAnimation(Animation.default.delay(2)) {
                    self.state.showSolution.toggle()
                }
            }){
                Text("Next")
            }.padding()
            Spacer()
        }
    }
}

struct CustomToggleTwo: View{
    @EnvironmentObject var state:SolutionState

    var body:some View{
        HStack{
            Spacer()
            Button(action:{
                withAnimation() {
                    self.state.showSolution.toggle()
                }
            }){
                Text("Next")
            }.padding()
            Spacer()
        }
    }
}