发布对象更改时 SwiftUI 视图不会刷新

问题描述 投票:0回答:1

在我的视图模型中,我有这个属性和方法:

@Published var cats: [Cat] = [] //this gets populated later

当我更新其中一只猫时:

func updateCatQuantity(_ cat:Cat, qty: Int) {
    if let index = cats(of: cat) {
        cats[index].quantity = qty
    }
}

视图不会刷新。

didSet
上的
cats
不会被调用。我认为这与
Cat
是一个类而不是一个结构有关。其定义如下:

class Cat: BaseMapperModel, Identifiable, Hashable {
    static func == (lhs: Cat, rhs: Cat) -> Bool {
       return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
    }

    var id = UUID()

    var title: String = ""
    var quantity: Int = 0

    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }

    override func mapping(map: Map) {
        title <- map["title"]
        quantity <- map["qty"]
    }
}

当猫的数量改变时如何让视图刷新?

swift swiftui objectmapper property-wrapper-published
1个回答
0
投票

有2个问题

  1. @Published
    仅在“值”改变时触发刷新。更改
    class
    中的变量不被视为“值”更改。

切换到

struct
是“简单”的改变。

struct Cat: Identifiable, Hashable {
    var id = UUID()

    var title: String = ""
    var quantity: Int = 0
}

但是问题#2 是一个更大的问题。通过覆盖

Hashable
,您将告诉 SwiftUI 仅在
View
更改时触发
id
重新加载。

要在 iOS 13-16 中观察

class
,该对象必须符合
ObservableObject
并用
@StateObject
@ObservedObject
@EnvironmentObject
包裹,在您想要看到变化的每个级别进行相应的操作。

class Cat: Identifiable, Hashable, ObservableObject {
    var id = UUID()

    @Published var title: String = ""
    @Published var quantity: Int = 0

    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
        hasher.combine(title)
        hasher.combine(quantity)
    }
    static func == (lhs: Cat, rhs: Cat) -> Bool {
        return lhs.id == rhs.id 
        && lhs.title == rhs.title
        && lhs.quantity == rhs.quantity
    }
}

在 iOS 17+ 中,您可以适当地使用

@Observable
代替
ObservableObject
以及
@State
@Bindable

@Observable
class Cat: Identifiable{
    var id = UUID()

    var title: String = ""
    var quantity: Int = 0
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
        hasher.combine(title)
        hasher.combine(quantity)
    }
    
    static func == (lhs: Cat, rhs: Cat) -> Bool {
        return lhs.id == rhs.id
        && lhs.title == rhs.title
        && lhs.quantity == rhs.quantity
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.