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