PMT*_*PMT 4 mvvm ios swift swiftui combine
每当 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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是尝试捕获@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
})
}
}
Run Code Online (Sandbox Code Playgroud)
View以相同的方式但试图捕获PassthroughSubject<>
.onReceive(viewModel.newItemOnFocus, perform: { itemUUID in
self.showPicker = itemUUID != nil // <-- This never gets called
})
Run Code Online (Sandbox Code Playgroud)
- - - - - 编辑 - - - - -
添加 MenuItemView,虽然 viewModel.tapOnMenuItem 总是被调用,所以我不确定它是否非常相关
菜单项视图在这里:
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
}
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
好吧,这就是 - 你的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
Run Code Online (Sandbox Code Playgroud)
2)
struct MenuItemView: View {
var item: MenuItem
@ObservedObject private var viewModel: MenuViewModel = MenuViewModel() // 2nd one
Run Code Online (Sandbox Code Playgroud)
因此,您修改一个实例,但订阅另一实例中的更改。就是这样。
.environmentObject
解决方案:通过或通过参数 from MenuView
to传递视图模型MenuItemView
。
归档时间: |
|
查看次数: |
7207 次 |
最近记录: |