sriram hegde
sriram hegde

Reputation: 2471

Transition not happening when data in model is being removed and added in swiftUi

***** I have updated My Model and ViewModel *****

I have a Card View and an array. I'm looping over that array to create an equal number of cards. I can transition and animate the first creation of card using the .onAppear method. I have two buttons to remove and add array items in a model. When I add and remove from an array using withAnimation I'm getting default fading transition. However I want transition(.scale). How do I get it?

Here is the Model:

struct Model {
    var dataArray : Array<Model.Data> =  [Data(), Data(), Data()]
        
    mutating func addToArray() {
        dataArray.append(Data())
    }
        
    mutating func removeFromArray() {
        dataArray.remove(at: 0)
    }
            
    struct Data : Identifiable {
        var id = UUID()
    }
}

Here is my ViewModel:

class ViewModelTest : ObservableObject {
    
    @Published var model = Model()
    
    var dataArray : Array<Model.Data> {
        model.dataArray
    }
    
    func addToArray() {
        model.addToArray()
    }
    
    func removeFromArray() {
        model.removeFromArray()
    }
    
}

Here is my View :

struct ContentView: View {
        
    @ObservedObject var viewModel = ViewModelTest()
    @State private var isLoading = false
        
    var body: some View {
          
    VStack {
        HStack {
            ForEach(viewModel.dataArray,  id: \.self) { _ in
                Group {
                    if self.isLoading {
                        Color.red
                            .frame(width: 100, height: 170)
                            .transition(.scale)
                    }
                }
            }
            .animation(.easeInOut(duration: 5))
            .onAppear {
                self.isLoading = true
            }
          
            HStack {
                Button(action: {
                    withAnimation(.easeInOut(duration: 1)) {
                        self.viewModel.addToArray()
                    }
                }) {
                    Text("add")
                }
              
                Button(action: {
                    withAnimation(.easeInOut(duration: 1)) {
                        self.viewModel.removeFromArray()
                    }
                }) {
                    Text("remove")
                }
            }
        }
    }         
}

I'm getting the following error: Generic struct ForEach requires that Model.Data conform to Hashable

Upvotes: 1

Views: 221

Answers (1)

Asperi
Asperi

Reputation: 257719

Here is a possible solution. (Note: your dataArray have to contain unique values, otherwise you should find a way to make them uniquely identified)

Tested with Xcode 12 / iOS 14

demo

struct ContentView: View {

    @ObservedObject var viewModel = ViewModelTest()
    @State private var isLoading = false

    var body: some View {

        VStack {
            HStack {
                ForEach(viewModel.model.dataArray, id: \.self) { _ in
                    if self.isLoading {
                        Color.red
                            .frame(width: 100, height: 170)
                            .transition(.scale)
                    }
                }
            }
            .animation(.easeInOut(duration: 1))
            .onAppear {
                self.isLoading = true
            }

            HStack {
                Button(action: {
                    self.viewModel.addToArray()
                }) {
                    Text("add")
                }

                Button(action: {
                    self.viewModel.removeFromArray()
                }) {
                    Text("remove")
                }
            }
        }
    }
}

Update: for SwiftUI 1.0 use the following (tested with Xcode 11.4 / iOS 13.4)

ForEach(viewModel.model.dataArray, id: \.self) { _ in
    Group {
      if self.isLoading {
        Color.red
            .frame(width: 100, height: 170)
            .transition(.scale)
    }}
}

Upvotes: 2

Related Questions