RachelRadford
RachelRadford

Reputation: 11

SwiftUI .overlay() causing data to be displayed incorrectly

I'm working on an app that calls an api and displays the data on 6 different cards. In the card view the data displays correctly. Once I place that view into another using .overlay() the UI is perfect but the data on each card is the same. Without .overlay() the data is correct but the UI is wrong. I've tried changing my ViewModel variable in the views to @EnvironmentObject, @StateObject, & @ObservedObject with no luck. I can't figure out if this is a bug or I am missing something. Any help is greatly appreciated.

This view displays data correctly:

import SwiftUI

struct TopActivityCardView: View {
   // @EnvironmentObject var vm: ViewModel
      @StateObject var vm = ViewModel()
       var timePeriod = ""
    
       var body: some View {
      
        ZStack {
        ScrollView{
            ForEach(vm.fetch(), id: \.title) { item in
               RoundedRectangle(cornerRadius: 20)
                .foregroundColor(Color.darkBlue)
            .frame(height: 120, alignment: .center)
            .padding(.top, 80)
            .overlay(

                ActivityTitleView(activityTitle: item.title)
            ).overlay(
                ActivityHoursView(workHours: item.timeframes.weekly.current)
            ).overlay(
                ActivityEllipisView()
            ).overlay(
                TimePeriodView(timePeriod: "Last Week", weeklyHrs: 
                item.timeframes.weekly.previous)
              )
            }
            
          }
            
        }

     }
}
    


struct TopActivityCardView_Previews: PreviewProvider {
    static var previews: some View {
        TopActivityCardView()
            .environmentObject(ViewModel())
    }
}

This view is where the problem occurs:

import SwiftUI


struct RectCardView: View {

    var colorArray: [(colorName: Color, imageName: String)] = [(Color.work, "icon-work"), 
    (Color.play, "icon-play"), (Color.study, "icon-study"), (Color.exercise, "icon- 
    exercise"), (Color.social, "icon-social"), (Color.selfCare, "icon-self-care")]
    
    // @StateObject var vm = ViewModel()

    @ObservedObject var vm = ViewModel()

    var body: some View {

            ZStack{

            ScrollView{

                ForEach(colorArray, id: \.imageName) { colorName, imageName in

                    RoundedRectangle(cornerRadius: 20)

                        .foregroundColor(colorName)

                        .frame(height: 110, alignment: .center)

                        .overlay(

                            Image(imageName)

                                .brightness(-0.2)

                                .frame(width: 60, height: 20, alignment: .topLeading)

                                .offset(x: 103, y: -60)
                            
                        ).clipped()
                    
                    /// If I take .overlay() off the cards display correct data but UI is 
                         not correct.
                    ///  With overlay UI is correct but data on cards is all the same.
                    
                        .overlay{

                            TopActivityCardView()

                                .padding(.top, -40)
                            
                        }
                        .padding(.top, 20)
                }
            }
        }
    }
}

struct RectCardView_Previews: PreviewProvider {
    static var previews: some View {`enter code here`
        RectCardView()
            .environmentObject(ViewModel())
    }
}

Upvotes: 1

Views: 486

Answers (1)

Gavin Morrow
Gavin Morrow

Reputation: 769

In TopActivityCardView, you are making a new view model (@StateObject var vm = ViewModel()).

It isn't using the same view model as RectCardView, so the data is different.

You could pass the view into TopActivityCardView by using an environment object:

// code…
struct TopActivityCardView: View {
    @EnvironmentObject var vm: ViewModel
    // more code…
}
.overlay{
    TopActivityCardView()
        .environmentObject(vm)
        .padding(.top, -40)                      
}

Upvotes: 1

Related Questions