访问和操作 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-model
和 activity
传递给 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)")
}
}
我有一个 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-model
和 activity
传递给 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)")
}
}