SwiftUI:调用objectWillChange.end()时未更新子视图

gijlo24d  于 2022-10-23  发布在  Swift
关注(0)|答案(1)|浏览(139)

我有一组嵌套在视图中的相当复杂的视图。当我触发按钮操作时,我通过我的viewModel类传递一个可选块,该类调用viewModel上的objectWillChange.send(),我知道它被触发是因为我的视图的其他部分正在更新。其中一个子视图(观察viewModel更改)不会更新,直到我单击它的一部分(更改viewModel.selectedIndex并触发重绘,以便我知道它正在侦听已发布的更改)。

为什么更新没有触发子视图(本例中为PurchaseItemGrid)重绘?

我在这里设置了呼叫以更新...

struct RightSideView: View {
    @ObservedObject var viewModel: TrenchesPurchases

    var body: some View {
        VStack {
            ...
            PurchaseItemGrid(viewModel: viewModel)      // <-- View not updating
            Button {
                viewModel.purchaseAction() {
                    viewModel.objectWillChange.send()   // <-- Triggers redraw, reaches breakpoint here
                }
            } label: {
                ...
            }
            ...
        }
    }
}

这里是调用可选的地方(我不仅在视觉上确认这是在视图重画的其他部分发生的,它在这里也命中断点)……

class TrenchesPurchases: ObservableObject, CanPushCurrency {

    // MARK: - Properties

    @Published private var model = Purchases()

    // MARK: - Properties: Computed

    var selectedIndex: Int {
        get { return model.selectedIndex }
        set { model.selectedIndex = newValue }
    }

    var purchaseAction: BlockWithBlock {
        { complete in                    
            ...

            complete?()
        }
    }
    ...
}

这是没有按预期更新的视图...

struct PurchaseItemGrid: View {

   @ObservedObject var viewModel: TrenchesPurchases

   var body: some View {
        VStack {
            itemRow(indices:  0...3)
            ...
        }
        ...
    }

    @ViewBuilder
    func itemRow(indices range: ClosedRange<Int>) -> some View {
        HStack {
            ForEach(viewModel.purchaseItems[range], id: \.id) { item in
                PurchaseItemView(item: item,
                                 borderColor: viewModel.selectedIndex == item.id ? .green : Color(Colors.oliveGreen))
                .onTapGesture { viewModel.selectedIndex = item.id }
            }
        }
    }
}

这是代码工作犬要的.

struct Purchases {

    // MARK: - Properties

    var selectedIndex = 15

    let items: [PurchaseItem] = buildCollectionOfItems()

    // MARK: - Functions

    // MARK: - Functions: Static

    // TODO: Define Comments
    static func buildCollectionOfItems() -> [PurchaseItem] {
        return row0() + row1() + row2() + row3()
}

static func row0() -> [PurchaseItem] {
    var items = [PurchaseItem]()

    let grenade = Ammo(ammo: .grenade)
    items.append(grenade)

        let bullets = Ammo(ammo: .bullets)
        items.append(bullets)

        let infiniteBullets = Unlock(mode: .defense)
        items.append(infiniteBullets)

        let unlimitedInfantry = Unlock(mode: .offense)
        items.append(unlimitedInfantry)

        return items
    }

    static func row1() -> [PurchaseItem] {
        var items = [PurchaseItem]()

        for unit in UnitType.allCases {
            let item = Unit(unit: unit)
            items.append(item)
        }

        return items
    }

    static func row2() -> [PurchaseItem] {
        var items = [PurchaseItem]()

        let brits = NationItem(nation: .brits)
        items.append(brits)

        let turks = NationItem(nation: .turks)
        items.append(turks)

        let usa = NationItem(nation: .usa)
        items.append(usa)

        let insane = DifficultyItem(difficulty: .insane)
        items.append(insane)

        return items
    }

    static func row3() -> [PurchaseItem] {
        var items = [PurchaseItem]()

        let offenseLootBox = Random(mode: .offense)
        items.append(offenseLootBox)

        let defenseLootBox = Random(mode: .defense)
        items.append(defenseLootBox)

        let currency = Currency(isCheckin: false)
        items.append(currency)

        let checkIn = Currency(isCheckin: true)
        items.append(checkIn)

        return items
    }
}
wmvff8tz

wmvff8tz1#

我遇到的问题是,PurchaseItemGrid注意到发布了观察到的项,但我试图触发的更改是在PurchaseItemView中没有观察到的对象。
我假设当PurchaseItemGrid观察到变化并重新绘制时,itemRow方法将重新绘制一个新的PurchaseItemView集合,然后更新它们的图像以匹配新的状态。
这进一步加剧了这种情况,因为onTapGesture触发了PurchaseItemView的重绘,老实说,我仍然不确定PurchaseItemGrid如何在其主体中仍然使用相同的PurchaseItemView的情况下重绘自己;但这可能与@ViewBuilder的工作方式有关,因为视图是用完全不同的方法创建的。
因此,长话短说:确保您要更新的每个视图都有某种形式的观察者,而不是依赖父视图的重绘来创建新的子视图。

相关问题