访问和操作 EnvironmentObject 中的数组项 [英] Accessing and manipulating array item in an 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-用户输入
确认Identifiable
和Equatable
.
迭代 activity.activities
并将您的 view-model
和 activity
传递给 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
包装器.
一个完整的工作示例.
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屋!