访问和操作 EnvironmentObject 中的数组项 [英] Accessing and manipulating array item in an EnvironmentObject

查看:28
本文介绍了访问和操作 EnvironmentObject 中的数组项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 EnvironmentObject 用于生成列表

class ActivityViewModel: ObservableObject {@Published var 活动 = [活动]()在里面() {self.Activity = ActivityService.fetchActivities()}}结构活动:可编码{变量 ID:UUID变量名称:字符串var 记录:[记录]初始化(名称:字符串){self.Id = UUID.init()self.Name = 姓名self.Records = [Record]()}}

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

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

我的父视图"代码:

ForEach(0..<activities.Activities.count, id: \.self) { 活动在堆栈{ActivityListItemView(activity: self.activities.Activities[activity])}}

我的孩子查看代码:

struct ActivityListItemView:查看{让活动:活动var主体:一些视图{NavigationLink(destination: ActivityDetail(Activity: activity)) {堆栈{虚拟堆栈{堆栈{文本(活动.名称)文本(\(activity.Records.count)记录")}}文本(">")}}.buttonStyle(PlainButtonStyle())}}

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

任何帮助将不胜感激.

添加活动类型

解决方案

这种方法类似于 Apple 在本教程中的方法.

https://developer.apple.com/tutorials/swiftui/handling-用户输入


确认IdentifiableEquatable.

<预><代码>struct Activity: Codable, Identifiable, Equatable {变量 ID:UUID变量名:字符串//var 记录:[记录]初始化(名称:字符串){self.id = UUID()self.name = 姓名//self.Records = [Record]()}}

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

 ForEach(viewModel.activities) { 活动在堆栈{ActivityListItemView(视图模型:视图模型,活动:活动)}}

ActivityListItemView中,找到其活动的索引

private var activityIndex: Int?{viewModel.activities.firstIndex(of: 活动)}

解包 activityIndex 并将 $viewModel.activities[index] 传递给 ActivityDetail

var body: some View {如果让索引 = 活动索引 {NavigationLink(destination: ActivityDetail(activity: $viewModel.activities[index])) {...}...}}

ActivityDetail中使用@Binding包装器.

<预><代码>struct ActivityDetail:查看{@Binding var 活动:活动var主体:一些视图{...}}


一个完整的工作示例.

class ActivityViewModel: ObservableObject {@Published var活动 = [活动]()在里面() {self.activities = [活动(名称:A"),活动(名称:B"),活动(名称:C"),活动(名称:D"),活动(名称:B");E")]}}struct Activity: Codable, Identifiable, Equatable {变量 ID:UUID变量名:字符串//var 记录:[记录]初始化(名称:字符串){self.id = UUID()self.name = 姓名//self.Records = [Record]()}}struct ActivityView:查看{@ObservedObject var viewModel = ActivityViewModel()var主体:一些视图{按钮(动作:{self.viewModel.activities.append(Activity(Name: "\(Date())")))}, 标签: {文本(按钮")})ForEach(viewModel.activities) { 活动在堆栈{ActivityListItemView(视图模型:视图模型,活动:活动)}}}}struct ActivityListItemView: 查看 {@ObservedObject var viewModel: ActivityViewModel让活动:活动私有变量活动索引:整数?{viewModel.activities.firstIndex(of: 活动)}var主体:一些视图{如果让索引 = 活动索引 {NavigationLink(destination: ActivityDetail(activity: $viewModel.activities[index])) {堆栈{虚拟堆栈{堆栈{文本(活动名称)//文本(\(activity.Records.count)记录")}}文本(">")}}.buttonStyle(PlainButtonStyle())}}}struct ActivityDetail:查看{@Binding var 活动:活动var主体:一些视图{文本(\(活动名称)")}}

I have an EnvironmentObject that I'm using to generate a list

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]()
    }
}

When I'm using this in the view, I can use a ForEach to access each value in the Activities array.

My issue is when I use a NavigationLink to pass this Activity to another view, it's not then using the EnvironmentObject

My 'parent view' code:

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

My child view code:

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())
    }
}

If I then update the viewModel, I need this to replicate into the child view. But I can't figure out how to make it use the EnvironmentObject, rather than just the variable I pass to the view.

Any help would be appreciated.

Edit: Added activity type

解决方案

This approach is similar to Apple's in this tutorials.

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


Confirm to Identifiable and 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]()
       }
   }

Iterate over activity.activities and pass your view-model and activity to ActivityListItemView

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

In ActivityListItemView, find index of its activity

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

Unwrap activityIndex and pass $viewModel.activities[index] to ActivityDetail

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

Use @Binding wrapper in ActivityDetail.


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


A complete working exammple.

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)")
    }
}

这篇关于访问和操作 EnvironmentObject 中的数组项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆