在SwiftUI中制作动态,可编辑的简单对象列表的最简单方法?

茶壶先生

我希望由一个具有子视图列表的母视图呈现一个可变字符串的动态数组,每个子视图均显示一个可编辑的字符串。同样,母视图将显示字符串的串联,每当在子视图中更新一个字符串时,这些字符串就会更新。

不能使用(1)ForEach(self.model.strings.indices)自组索引可以改变的,并且不能使用(2)ForEach(self.model.strings) { string in由于子视图想要编辑字符串,但string将是不可改变的。

我发现进行这项工作的唯一方法是利用@EnvironmentObject随参数一起传递的。这确实很笨拙,而且在进攻方面也很有限。

但是,我是swiftui的新手,我相信有更好的方法可以解决此问题,请告诉我们!

这是我现在所拥有的:

import SwiftUI

struct SimpleModel : Identifiable { var id = UUID(); var name: String }
let simpleData: [SimpleModel] = [SimpleModel(name: "text0"), SimpleModel(name: "text1")]
final class UserData: ObservableObject { @Published var simple = simpleData }

struct SimpleRowView: View {
  @EnvironmentObject private var userData: UserData
  var simple: SimpleModel
  var simpleIndex: Int { userData.simple.firstIndex(where: { $0.id == simple.id })! }
  var body: some View {
    TextField("title", text: self.$userData.simple[simpleIndex].name)
  }
}

struct SimpleView: View {
  @EnvironmentObject private var userData: UserData
  
  var body: some View {
    let summary_binding = Binding<String>(
      get: {
        var arr: String = ""
        self.userData.simple.forEach { sim in arr += sim.name }
        return arr;
      },
      set: { _ = $0 }
    )
    
    return VStack() {
      TextField("summary", text: summary_binding)
      ForEach(userData.simple) { tmp in
        SimpleRowView(simple: tmp).environmentObject(self.userData)
      }
      Button(action: { self.userData.simple.append(SimpleModel(name: "new text"))}) {
        Text("Add text")
      }
    }
  }
}

EnironmentObject被创建和传递SimpleView().environmentObject(UserData())从AppDelegate中。

编辑:

作为参考,如果有人找到了,下面是@ pawello2222建议的使用ObservedObject而不是EnvironmentObject的完整解决方案:

import SwiftUI

class SimpleModel : ObservableObject, Identifiable {
  let id = UUID(); @Published var name: String
  init(name: String) { self.name = name }
}

class SimpleArrayModel : ObservableObject, Identifiable {
  let id = UUID(); @Published var simpleArray: [SimpleModel]
  init(simpleArray: [SimpleModel]) { self.simpleArray = simpleArray }
}

let simpleArrayData: SimpleArrayModel = SimpleArrayModel(simpleArray: [SimpleModel(name: "text0"), SimpleModel(name: "text1")])

struct SimpleRowView: View {
  @ObservedObject var simple: SimpleModel
  var body: some View {
      TextField("title", text: $simple.name)
  }
}

struct SimpleView: View {
  @ObservedObject var simpleArrayModel: SimpleArrayModel
  
  var body: some View {
    let summary_binding = Binding<String>(
      get: { return self.simpleArrayModel.simpleArray.reduce("") { $0 + $1.name } },
      set: { _ = $0 }
    )
    
    return VStack() {
      TextField("summary", text: summary_binding)
      ForEach(simpleArrayModel.simpleArray) { simple in
        SimpleRowView(simple: simple).onReceive(simple.objectWillChange) {_ in self.simpleArrayModel.objectWillChange.send()}
      }
      Button(action: { self.simpleArrayModel.simpleArray.append(SimpleModel(name: "new text"))}) {
        Text("Add text")
      }
    }
  }
}
pawello2222

您实际上并不需要@EnvironmentObject(它将在您环境中的所有视图中全局可用)。

您可能要@ObservedObject改用(或@StateObject使用SwiftUI 2.0):

...
return VStack {
    TextField("summary", text: summary_binding)
    ForEach(userData.simple, id:\.id) { tmp in
        SimpleRowView(userData: self.userData, simple: tmp) // <- pass userData to child views
    }
    Button(action: { self.userData.simple.append(SimpleModel(name: "new text")) }) {
        Text("Add text")
    }
}
struct SimpleRowView: View {
    @ObservedObject var userData: UserData
    var simple: SimpleModel
    ...
}

请注意,如果数据不是恒定的,则应使用动态ForEach循环(带有显式id参数):

ForEach(userData.simple, id:\.id) { ...

但是,当您和上SimpleModel堂课时,可以获得最佳结果ObservableObject这是一个更好的解决方案,如何正确执行:

SwiftUI更新父级NavigationView的数据

另外,您可以简化summary_binding使用reduce

let summary_binding = Binding<String>(
    get: { self.userData.simple.reduce("") { $0 + $1.name } },
    set: { _ = $0 }
)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在Angular中制作editForm的最简单方法是什么?

来自分类Dev

这是制作“动画”文本的最简单方法吗?

来自分类Dev

这是制作“动画”文本的最简单方法吗?

来自分类Dev

用波浪制作复杂 div 的最简单方法

来自分类Dev

在OpenGL(OpenTK)中显示简单图像的最简单方法?

来自分类Dev

在Java中创建简单解析的最简单方法

来自分类Dev

在OpenGL(OpenTK)中显示简单图像的最简单方法?

来自分类Dev

在Groovy中实现单方法接口的最简单方法?

来自分类Dev

在Microsoft Word中制作多页图像的最简单方法?

来自分类Dev

在 SQL Management Studio 中编辑单个单元格值的最简单方法

来自分类Dev

收集动态指令执行计数的最简单方法?

来自分类Dev

查找动态数组均值的最简单方法

来自分类Dev

检查动态IP更改的最简单方法

来自分类Dev

用新值列表替换数据框中的值列表的最简单方法

来自分类Dev

努力从表中动态选择/联接值的最简单方法

来自分类Dev

在.NET 4.5中动态生成代码的最简单方法是什么?

来自分类Dev

使用构造函数Javascript中的field方法提供对象的最简单方法

来自分类Dev

创建坐标列表的最简单方法是什么?

来自分类Dev

在Python中加入整数列表的最简单方法?

来自分类Dev

对Vector3的列表进行排序的最简单方法

来自分类Dev

测试404 URL列表的最简单方法?

来自分类Dev

用Java筛选列表的最简单方法是什么?

来自分类Dev

创建坐标列表的最简单方法是什么?

来自分类Dev

Tcpclinet C#发送对象的最简单方法

来自分类Dev

“模拟”实现仅属性协议的对象的最简单方法

来自分类Dev

创建返回对象引用的成员函数的最简单方法

来自分类Dev

检查包含列表中字符串的字符串的最简单方法?

来自分类Dev

检查列表中是否有多个项目的最简单方法?

来自分类Dev

比较bash中两个文件列表的最简单方法?

Related 相关文章

  1. 1

    在Angular中制作editForm的最简单方法是什么?

  2. 2

    这是制作“动画”文本的最简单方法吗?

  3. 3

    这是制作“动画”文本的最简单方法吗?

  4. 4

    用波浪制作复杂 div 的最简单方法

  5. 5

    在OpenGL(OpenTK)中显示简单图像的最简单方法?

  6. 6

    在Java中创建简单解析的最简单方法

  7. 7

    在OpenGL(OpenTK)中显示简单图像的最简单方法?

  8. 8

    在Groovy中实现单方法接口的最简单方法?

  9. 9

    在Microsoft Word中制作多页图像的最简单方法?

  10. 10

    在 SQL Management Studio 中编辑单个单元格值的最简单方法

  11. 11

    收集动态指令执行计数的最简单方法?

  12. 12

    查找动态数组均值的最简单方法

  13. 13

    检查动态IP更改的最简单方法

  14. 14

    用新值列表替换数据框中的值列表的最简单方法

  15. 15

    努力从表中动态选择/联接值的最简单方法

  16. 16

    在.NET 4.5中动态生成代码的最简单方法是什么?

  17. 17

    使用构造函数Javascript中的field方法提供对象的最简单方法

  18. 18

    创建坐标列表的最简单方法是什么?

  19. 19

    在Python中加入整数列表的最简单方法?

  20. 20

    对Vector3的列表进行排序的最简单方法

  21. 21

    测试404 URL列表的最简单方法?

  22. 22

    用Java筛选列表的最简单方法是什么?

  23. 23

    创建坐标列表的最简单方法是什么?

  24. 24

    Tcpclinet C#发送对象的最简单方法

  25. 25

    “模拟”实现仅属性协议的对象的最简单方法

  26. 26

    创建返回对象引用的成员函数的最简单方法

  27. 27

    检查包含列表中字符串的字符串的最简单方法?

  28. 28

    检查列表中是否有多个项目的最简单方法?

  29. 29

    比较bash中两个文件列表的最简单方法?

热门标签

归档