访问和操作 EnvironmentObject 中的数组项

Accessing and manipulating array item in an EnvironmentObject

我有一个 EnvironmentObject 用于生成列表

class ActivityViewModel: ObservableObject {
    @Published var Activities = [Activity]()
    
    init() {
        self.Activities = ActivityService.fetchActivities()
    }
}

struct Activity: Codable {
    var Id: UUID
    var Name: String
    var Records: [Record]
    
    init(Name:String) {
        self.Id = UUID.init()
        self.Name = Name
        self.Records = [Record]()
    }
}

当我在视图中使用它时,我可以使用 ForEach 访问 Activities 数组中的每个值。

我的问题是当我使用 NavigationLink 将此 Activity 传递给另一个视图时,它并没有使用 EnvironmentObject

我的'parent view'代码:

ForEach(0..<activities.Activities.count, id: \.self) { activity in
    HStack {
        ActivityListItemView(activity: self.activities.Activities[activity])
    }
}

我的child查看代码:

struct ActivityListItemView: View {
    let activity: Activity
    
    var body: some View {
        NavigationLink(destination: ActivityDetail(Activity: activity)) {
            HStack {
                VStack {
                    HStack {
                        Text(activity.Name)
                        Text("\(activity.Records.count) records")
                    }
                }
                
                Text(">")
            }
        }
        .buttonStyle(PlainButtonStyle())
    }
}

如果我随后更新 viewModel,我需要将其复制到 child 视图中。但我不知道如何让它使用 EnvironmentObject,而不仅仅是我传递给视图的变量。

如有任何帮助,我们将不胜感激。

编辑:添加了activity类型

此方法类似于本教程中 Apple 的方法。

https://developer.apple.com/tutorials/swiftui/handling-user-input


确认 Identifiable Equatable


   struct Activity: Codable, Identifiable, Equatable {
       var id: UUID
       var name: String
   //    var Records: [Record]
       
       init(Name:String) {
           self.id = UUID()
           self.name = Name
   //        self.Records = [Record]()
       }
   }

迭代 activity.activities 并将您的 view-modelactivity 传递给 ActivityListItemView

   ForEach(viewModel.activities) { activity in
     HStack {
         ActivityListItemView(viewModel: viewModel, activity: activity)
     }
 }

ActivityListItemView中找到其activity

的索引
private var activityIndex: Int? {
     viewModel.activities.firstIndex(of: activity)
  }

展开 activityIndex 并将 $viewModel.activities[index] 传递给 ActivityDetail

var body: some View {
      if let index = activityIndex {
          NavigationLink(destination: ActivityDetail(activity: $viewModel.activities[index])) {
              ...
          }
          ...
      }
  }

ActivityDetail 中使用 @Binding 包装器。


    struct ActivityDetail: View {
        @Binding var activity: Activity
        
        var body: some View {
            ...
        }
    }

一个完整的工作示例。

class ActivityViewModel: ObservableObject {
    @Published var activities = [Activity]()
    
    init() {
        self.activities = [Activity(Name: "A"), Activity(Name: "B"), Activity(Name: "C"), Activity(Name: "D"), Activity(Name: "E")]
    }
}

struct Activity: Codable, Identifiable, Equatable {
    var id: UUID
    var name: String
//    var Records: [Record]
    
    init(Name:String) {
        self.id = UUID()
        self.name = Name
//        self.Records = [Record]()
    }
}


struct ActivityView: View {
   @ObservedObject  var viewModel = ActivityViewModel()
    var body: some View {
        Button(action: {
            self.viewModel.activities.append(Activity(Name: "\(Date())"))
        }, label: {
            Text("Button")
        })
        ForEach(viewModel.activities) { activity in
            HStack {
                ActivityListItemView(viewModel: viewModel, activity: activity)
            }
        }

    }
}


struct ActivityListItemView: View {
    
    @ObservedObject var viewModel: ActivityViewModel
    
    let activity: Activity
    
    private var activityIndex: Int? {
        viewModel.activities.firstIndex(of: activity)
    }
    
    var body: some View {
        if let index = activityIndex {
            NavigationLink(destination: ActivityDetail(activity: $viewModel.activities[index])) {
                HStack {
                    VStack {
                        HStack {
                            Text(activity.name)
    //                        Text("\(activity.Records.count) records")
                        }
                    }
                    Text(">")
                }
            }
            .buttonStyle(PlainButtonStyle())
        }
    }
}


struct ActivityDetail: View {
    @Binding var activity: Activity
    
    var body: some View {
        Text("\(activity.name)")
    }
}