当 ObservedObject 更改时,在 SwiftUI 视图中未调用 onReceive
Posted
技术标签:
【中文标题】当 ObservedObject 更改时,在 SwiftUI 视图中未调用 onReceive【英文标题】:onReceive not getting called in SwiftUI View when ObservedObject changes 【发布时间】:2020-02-27 18:42:12 【问题描述】:每当来自 ObservedObject 的变量发生变化时,我都无法在 SwiftUI 视图中触发 onReceive 方法。
我尝试了两种方法:使用 @Publish 和使用 PassthroughSubject
这是视图模型
class MenuViewModel: ObservableObject
@Published var selectedItems = Set<UUID>()
@Published var currentFocusItem: UUID?
// Output
let newItemOnFocus = PassthroughSubject<(UUID?), Never>()
// This function gets called good :)
func tapOnMenuItem(_ item: MenuItem)
if selectedItems.contains(item.id)
//These changes should trigger the onReceive?
currentFocusItem = item.id
newItemOnFocus.send(item.id)
else
selectedItems.insert(item.id)
currentFocusItem = nil
newItemOnFocus.send(nil)
Here is the View 试图捕捉 @Published var currentFocusItem
中的变化struct MenuView: View
@ObservedObject private var viewModel: MenuViewModel
@State var showPicker = false
@State private var menu: Menu = Menu.mockMenu()
init(viewModel: MenuViewModel = MenuViewModel())
self.viewModel = viewModel
var body: some View
VStack
List(menu.items, selection: $viewModel.selectedItems) item in
MenuItemView(item: item)
Divider()
getBottomView(showPicker: showPicker)
.navigationBarTitle("Title")
.navigationBarItems(trailing: Button(action: closeModal)
Image(systemName: "xmark")
)
.onReceive(viewModel.$currentFocusItem, perform: itemUUID in
self.showPicker = itemUUID != nil // <-- This only gets called at launch time
)
视图以相同的方式,但试图捕捉 PassthroughSubject
.onReceive(viewModel.newItemOnFocus, perform: itemUUID in
self.showPicker = itemUUID != nil // <-- This never gets called
)
---------编辑----------
添加 MenuItemView,虽然 viewModel.tapOnMenuItem 总是被调用,所以我不确定它是否非常相关
MenuItemView 在这里:
struct MenuItemView: View
var item: MenuItem
@ObservedObject private var viewModel: MenuViewModel = MenuViewModel()
@State private var isSelected = false
var body: some View
HStack(spacing: 24)
Text(isSelected ? " 1 " : item.icon)
.font(.largeTitle)
.foregroundColor(.blue)
.bold()
VStack(alignment: .leading, spacing: 12)
Text(item.name)
.bold()
Text(item.description)
.font(.callout)
Spacer()
Text("\(item.points)\npoints")
.multilineTextAlignment(.center)
.padding()
.onTapGesture
self.isSelected = true
self.viewModel.tapOnMenuItem(self.item). // <-- Here tapOnMenuItem gets called
func quantityText(isItemSelected: Bool) -> String
return isItemSelected ? "1" : item.icon
我做错了什么?
【问题讨论】:
请告诉我们MenuItem
以及tapOnMenuItem
的名称。
@Asperi 完成!它总是被正确调用,所以我认为这并不重要
【参考方案1】:
嗯,就是这样 - 你的 MenuView
和 MenuItemView
使用不同的视图模型实例
1)
struct MenuView: View
@ObservedObject private var viewModel: MenuViewModel
@State var showPicker = false
@State private var menu: Menu = Menu.mockMenu()
init(viewModel: MenuViewModel = MenuViewModel()) // 1st one created
2)
struct MenuItemView: View
var item: MenuItem
@ObservedObject private var viewModel: MenuViewModel = MenuViewModel() // 2nd one
因此,您修改了一个实例,但订阅了另一个实例的更改。就是这样。
解决方案:通过.environmentObject
或通过参数从MenuView
传递视图模型到MenuItemView
。
【讨论】:
天哪!我做了多么愚蠢的事情?♀️!非常感谢你是完全正确的!我将它作为参数传递,它现在可以工作了!以上是关于当 ObservedObject 更改时,在 SwiftUI 视图中未调用 onReceive的主要内容,如果未能解决你的问题,请参考以下文章
@ObservedObject 更改后 SwiftUI 视图未更新
为啥我的@ObservedObject 没有在我的视图中执行更改?