SwiftUI视图层次结构中的变量传递

3

我有一个关于我的Swift/SwiftUI应用程序架构的问题,它由一个ListView、详细视图和详细视图包含2个输入视图组成。具体来说,我想知道这是否是正确的方法。

架构如下:

列表视图启动视图模型控制器的@StateObject。

@StateObject var viewModel = ListViewModelController()

视图模型控制器:

class ListViewModelController: ObservableObject {
@Published var model: ListViewModel

init() {
    self.model = ListViewModel()
 }
}

列表视图模型如下:

struct Exercise: Hashable, Identifiable {
let id =  UUID()
var name: String
var weight: String
var repetitions: String
}

struct ListViewModel {
var exercises = [
    Exercise(name: "crunches", weight: "80 kg", repetitions: "100"),
    Exercise(name: "curls", weight: "10 kg", repetitions: "12"),
    Exercise(name: "dips", weight: "Bodyweight", repetitions: "10")
]
}

我将exercise变量传递给详细视图的方式如下: ```html

我将exercise变量通过以下方式传递给详细视图:

```
List {
        ForEach($viewModel.model.exercises, id: \.self) {$exercise in
            ExerciseConfigutationView(exercise: $exercise)
        }
        .onDelete(perform: delete)
        .onMove(perform: move)
    }

详细视图接受“exercise”变量作为绑定:
@Binding var exercise: Exercise

问题是,每次我尝试呈现ListView时,程序会在没有警告或错误的情况下冻结。我认为我对绑定/属性包装器有所误解。
谢谢你的帮助。

1
我认为你多了一层,应该直接将练习数组放在控制器类中(对我来说这才是真正的视图模型)。 - Joakim Danielson
1
不确定这是否是您的问题,但有些事情您应该知道。只有在计划在视图内修改该值并希望在其他地方保留这些更改时,才应使用@Binding。如果您只是读取数据,请将其更改为let表达式。如果您的变量是@Published,SwiftUI仍然会在数据更改时更新视图。 - aeskreis
1
原因不在提供的代码中。 - Asperi
1个回答

2

ForEach使用id: \.self是错误的,但更严重的问题是,在SwiftUI中我们不使用视图模型对象,只使用模型对象。视图数据结构已经是SwiftUI用来创建和更新实际视图(如UILabel等)的视图模型。

这是已修复的代码:

@StateObject var model = ListModel()

//The List model:
class ListModel: ObservableObject {
    @Published var var exercises = [Exercise(name: "crunches", weight: "80 kg", repetitions: "100"),
                                    Exercise(name: "curls", weight: "10 kg", repetitions: "12"),
                                    Exercise(name: "dips", weight: "Bodyweight", repetitions: "10")]
}

struct Exercise: Hashable, Identifiable {
    let id =  UUID()
    var name: String
    var weight: String
    var repetitions: String
}

// Pass the exercise variable to the detail view in the following way:
List {
        ForEach($model.exercises) { $exercise in
            ExerciseConfigurationView(exercise: $exercise)
        }
        .onDelete(perform: delete)
        .onMove(perform: move)
    }


// pass the exercise variable to the detail view in the following way:
@Binding var exercise: Exercise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接