I Have a struct called line, which contains a bool called isDone.
struct Line : Hashable {
var isDone : Bool = false
var text : String
}
My viewmodel contains an array of these, once a line is entered the isDone is set to true.
class ViewModel: ObservableObject {
@Published var lines : [Line] = []
@Published var currentRowIndex : Int = 0
func EnterWord() {
lines[currentRowIndex].isDone = true
currentRowIndex = 1
}
}
When the line is entered I would like to have a 3D animation as seen below.
struct Line : View{
var line : Line
var body: some View {
Text(line.tex)
.rotation3DEffect(
Angle.degrees(line.isDone ? 180: 0),
axis: (1,0,0),
perspective: 0)
.animation(.linear(duration: 4.0), value: 180)
}
}
struct MainView: View {
@ObservedObject var viewModel : ViewModel = ViewModel()
var body: some View {
VStack(spacing:0){
ForEach(viewModel.lines, id: \.self){ line in
Line(line: line)
}
Button(action: {
viewModel.Enter()
})
{
Text("Add")
}
}
}
}
The rotation is shown but not animated, does the lack of animation have something to do with me using a struct instead of an ObservableObject? or is the animation code itself wrong?
CodePudding user response:
You can't use the ForEach
View struct with id:\.self
when using value types, you have to either supply the name of the identifier property or make your data conform to Identifiable
that has an id
property. e.g.
struct Line : Identifiable {
let id = UUID()
var isDone = false
var text: String
}
ForEach(model.lines) { line in
This is because the ForEach
needs to know the identifier to track changes, because with value types they are copied around and there is no reference to track.
Also you shouldn't init your model lifetime manager object with @ObservableObject
because it creates a new object every time the View is init which is on every state change of the parent. You can use @StateObject
instead if you want the object to be destroyed when this View dissapears. If you want it for the lifetime of your app you can init it as a singleton or global and then use @ObservedObject var = Model.shared
.
CodePudding user response:
remove perspective and try like this .rotation3DEffect(.degrees(line.isDone ? 180: 0), axis: (x: 1, y: 0, z: 0))