首页 > 解决方案 > SwiftUI 跨视图和视图模型保持数据最新

问题描述

我来自一个react-native背景,我无法理解 SwiftUI 中 MVVM 的特定部分:拥有相同实体的多个视图。

我正在构建一个带有帖子的简单社交媒体应用程序。这些帖子可以在Homepage, 和Profile任何用户的页面上查看。

这就是视图模型的样子

struct HomepagePosts: ObservableObject {
  @Published var posts = [Post]()

  ... rest of logic
}

struct ProfilePosts: ObservableObject {
  @Published var posts = [Post]()

  ... rest of logic
}

我的问题如下。如果用户刚刚发布了帖子,该帖子将显示在主页和他的个人资料中。如果用户决定更新帖子怎么办?帖子将如何在所有地方更新?

在 React 中,这是通过规范化状态来完成的。不是保留单独的posts数组,而是保留 2 个 s 数组,以及一个以as 键和整个对象作为值的postId字典。这样,更新帖子就会在一个地方更新它,并且每个视图都会直接更新。postIdPost

你如何在 SwiftUI 中做到这一点?

标签: iosswiftswiftui

解决方案


这里有一些代码来说明上面的评论。我相信你想要像这样构造它,只有一个模型对象。

struct Post: Identifiable {
  let id: String
  let text: String
}

class Model: ObservableObject {
  @Published var posts: [Post] = []
}

@main
struct TestApp: App {
  // @StateObject var model = Model()
  var body: some Scene {
    WindowGroup {
      Homepage()
       // .environmentObject(model)
    }
  }
}

struct Homepage: View {
  // @EnvironmentObject var model: Model
  @StateObject var model = Model() // holds array of homepage posts
  @State private var newPost: String = ""
  @State private var showProfile = false
  var body: some View {
    VStack {
      TextField("new post", text: $newPost) { _ in
      } onCommit: {
        model.posts.append(Post(id: UUID().uuidString, text: newPost))
        newPost = ""
      }
      Divider()
      ScrollView {
        ForEach(model.posts) { post in
          Text(post.text).padding()
        }
      }
      Divider()
      Button("Profile") {
        showProfile = true
      }
      .sheet(isPresented: $showProfile) {
        Profile()
      }
    }
    .padding()
  }
}

struct Profile: View {
  // @EnvironmentObject var model: Model
  @StateObject var model = Model() // holds array of profile posts
  var body: some View {
    Text("You have \(model.posts.count) posts")
  }
}

推荐阅读