我想更改速率参数并在ForEach中显示。
// ViewModel.swift
@MainActor final class ViewModel: ObservableObject {
let serviceContainer: ServiceContainerProtocol
@Published var funds: [FundModel] = []
...
init(serviceContainer: ServiceContainerProtocol) {
self.serviceContainer = serviceContainer
Task { await getFunds() }
...
}
...
}// FundView.swift
struct FundView: View {
@StateObject private var viewModel: ViewModel
init(serviceContainer: ServiceContainerProtocol) {
self._viewModel = StateObject(wrappedValue: ViewModel(serviceContainer: serviceContainer))
}
var body: some View {
ScrollView {
VStack {
ForEach(viewModel.funds, id: \.fundCode) { fund in
VStack {
Text(String(fund.rate))
Button("Add 5") {
if let index = viewModel.funds.firstIndex(where: { $0.fundCode == fund.fundCode }) {
viewModel.funds[index].rate += 5
}
}
}
}
}
}
}
}如果我使用Struct作为模型,视图按预期进行了更新。
// FundModel.swift
struct FundModel: Decodable {
let fundCode: String
...
// Internal - Not related to api.
var rate: Int = 0
...
// MARK: CodingKeys
private enum CodingKeys: String, CodingKey {
case fundCode
...
}
// MARK: Decodable
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
fundCode = try container.decode(String.self, forKey: .fundCode)
...
}
}如果我使用类作为模型,视图没有更新。
// FundModel.swift
final class FundModel: Decodable {
let fundCode: String
...
// Internal - Not related to api.
var rate: Int = 0
...
// MARK: CodingKeys
private enum CodingKeys: String, CodingKey {
case fundCode
...
}
// MARK: Decodable
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
fundCode = try container.decode(String.self, forKey: .fundCode)
...
}
}我想使用Class作为模型,因为它需要从某些超级类继承一些属性。
对于SwiftUI透视图来说,Struct模型和类模型有什么区别,为什么当我使用类模型而不是Struct模型时,视图没有更新?
注意: FundModel在其他地方符合Equtable和Hashable。
发布于 2022-04-29 08:40:17
使用class ViewModel: ObservableObject {...} (没有@MainActor)和viewModel.objectWillChange.send()来尝试这种方法,如下面的示例代码所示:
struct FundView: View {
@StateObject private var viewModel: ViewModel
init(serviceContainer: ServiceContainerProtocol) {
self._viewModel = StateObject(wrappedValue: ViewModel(serviceContainer: serviceContainer))
}
var body: some View {
ScrollView {
VStack {
ForEach(viewModel.funds, id: \.fundCode) { fund in
VStack {
Text(String(fund.rate))
Button("Add 5") {
if let index = viewModel.funds.firstIndex(where: { $0.fundCode == fund.fundCode }) {
viewModel.objectWillChange.send() // <-- here
viewModel.funds[index].rate += 5
}
}
}
}
}
}
}
}
final class FundModel: Decodable {
let fundCode: String
var rate: Int = 0
//....
}发布于 2022-04-29 08:23:25
当@Published var更改时,视图将更新。您的@Published var是一个FundModel数组。
结构不是可变的实体,所以当您使用struct时,数组实际上将对象替换为一个新的对象。系统识别数组中的更改并将其发布到视图中。
类是可变的,所以当您更改类内的速率时,仍然有相同的实例。因此,FundModel的数组不会改变:它仍然包含完全相同的元素,即使其中一个元素已经更改了一个内部变量。
@Published包装器无法检测数组成员的内部变量是否已更改:它只检测数组内部有不同元素的情况。
结论:struct需要创造一个新的元素来改变,@Published认识到了这一点。class可以更改,因此对于@Published,对象仍然是相同的(数组没有改变)。
https://stackoverflow.com/questions/72054710
复制相似问题