访问和操作 EnvironmentObject 中的数组项
Posted
技术标签:
【中文标题】访问和操作 EnvironmentObject 中的数组项【英文标题】:Accessing and manipulating array item in an EnvironmentObject 【发布时间】:2021-01-10 12:26:06 【问题描述】:我有一个 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
我的“父视图”代码:
ForEach(0..<activities.Activities.count, id: \.self) activity in
HStack
ActivityListItemView(activity: self.activities.Activities[activity])
我的孩子查看代码:
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,我需要将其复制到子视图中。但我不知道如何让它使用EnvironmentObject
,而不仅仅是我传递给视图的变量。
任何帮助将不胜感激。
编辑:添加活动类型
【问题讨论】:
Activity
是什么类型?
离题,但属性名称应以小写字母开头。
刚刚编辑添加活动。
您需要对已发布数组的元素使用绑定(因为元素是值,所以如果直接传递则复制)。请参阅***.com/a/59001742/12299030 中的场景示例。
谢谢,我现在去看看!
【参考方案1】:
此方法与本教程中的 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-model
和activity
传递给ActivityListItemView
ForEach(viewModel.activities) activity in
HStack
ActivityListItemView(viewModel: viewModel, activity: activity)
在ActivityListItemView
,找到它的活动索引
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)")
【讨论】:
以上是关于访问和操作 EnvironmentObject 中的数组项的主要内容,如果未能解决你的问题,请参考以下文章
如何使用@EnvironmentObject 在 SwiftUI 中自动填充和更新列表?
ObjectBinding 和 EnvironmentObject 有啥区别?
SwiftUI中如何使用@EnvironmentObject在AppDelegate和SceneDelegate/Views之间共享数据