Mvvm 为什么';将ViewModel添加到我的SwiftUI应用程序后,我的UI是否会更新?

Mvvm 为什么';将ViewModel添加到我的SwiftUI应用程序后,我的UI是否会更新?,mvvm,swiftui,viewmodel,combine,Mvvm,Swiftui,Viewmodel,Combine,我一直在关注,从第一部分和第二部分开始。现在我正试图将我在那里学到的知识转移到我自己的小测试应用程序中,特别是在混合中添加一个ViewModel Peter的应用程序有一个单屏幕界面,而我想使用第二个屏幕为新元素输入几条数据,当用户单击“保存新元素”时,它被添加到数组中,然后返回到第一个屏幕 在添加ViewModel代码之前,它完全按照预期工作:创建新元素、添加到数组、更新UI。它还可用于更新现有图元 添加ViewModel代码后,它几乎可以正常工作。已创建新元素,并将其添加到数组中但是,用户界

我一直在关注,从第一部分和第二部分开始。现在我正试图将我在那里学到的知识转移到我自己的小测试应用程序中,特别是在混合中添加一个
ViewModel

Peter的应用程序有一个单屏幕界面,而我想使用第二个屏幕为新元素输入几条数据,当用户单击“保存新元素”时,它被添加到数组中,然后返回到第一个屏幕

在添加
ViewModel
代码之前,它完全按照预期工作:创建新元素、添加到数组、更新UI。它还可用于更新现有图元

添加
ViewModel
代码后,它几乎可以正常工作。已创建新元素,并将其添加到数组中但是,用户界面没有更新,我不明白为什么不更新。

这是我的密码:

import Foundation
import SwiftUI
import Combine

struct Tournament: Identifiable {
    var id = UUID().uuidString
    var name: String
    var location: String = "Franchises"
    var date: Date = Date()
}

#if DEBUG
var blankTournament = Tournament(name: "")
var testTournamentData = [
    Tournament(name: "Tournament 1"),
    Tournament(name: "Tournament 2"),
    Tournament(name: "Tournament 3"),
]
#endif

struct ContentView: View {
    @ObservedObject var tournamentListVM = TournamentListVM()

    var body: some View {
        NavigationView {
            VStack {
                List(tournamentListVM.tournamentCellVMs) { tournamentCellVM  in
                    NavigationLink(
                        destination: TournamentDetails(tournament: tournamentCellVM.tournament),
                        label: { TournamentCell(tournamentCellVM: tournamentCellVM) }
)}}
            .navigationTitle("All in Two (\(tournamentListVM.tournamentCellVMs.count))")
            .navigationBarItems(
                trailing: NavigationLink(
                    destination: TournamentDetails(addingNewTournament: true))
                        { Image(systemName: "plus") }
)}}}

struct TournamentCell: View {
    @ObservedObject var tournamentCellVM: TournamentCellVM

    var body: some View {
        VStack(alignment: .leading) {
            Text(tournamentCellVM.tournament.name)
        }
    }
}

struct TournamentDetails: View {
    @Environment(\.presentationMode) var presentationMode // used to dismiss the view
    @ObservedObject var tournamentListVM = TournamentListVM()

    @State var tournament = blankTournament

    var addingNewTournament: Bool = false
    var index: Int? // needed when updating an existing record

    var body: some View {
        Form {
            Section(header: Text("Tournament Info")) {
                TextField("Name", text: $tournament.name)
                TextField("Location", text: $tournament.location)
                DatePicker(selection: $tournament.date, displayedComponents: .date) { Text("Date") }
            }
            Section { Button(action: {
                if addingNewTournament  { tournamentListVM.createTournament(tournament) }
                else                            { tournamentListVM.updateTournament(tournament) }
                presentationMode.wrappedValue.dismiss()
            }) { Text(addingNewTournament ? "Save Tournament" : "Update Tournament") }
}}}}

class TournamentListVM: ObservableObject {
    @Published var tournamentCellVMs = [TournamentCellVM]()

    private var cancellables = Set<AnyCancellable>()

    init() {
        self.tournamentCellVMs = testTournamentData.map { tournament in
            TournamentCellVM(tournament: tournament)
        }
    }

    func createTournament(_ tournament: Tournament) {
        print (tournamentCellVMs.count)
        tournamentCellVMs.append(TournamentCellVM(tournament: tournament))
        print (tournamentCellVMs.count)
    }

    func updateTournament(_ tournament: Tournament) {
    }
}

class TournamentCellVM: ObservableObject, Identifiable {
    @Published var tournament: Tournament

    var id = ""

    private var cancellables = Set<AnyCancellable>()

    init(tournament: Tournament) {
        self.tournament = tournament

        $tournament
            .map { tournament in tournament.id }
            .assign(to: \.id, on: self)
            .store(in: &cancellables)
}}
<代码>导入基础 导入快捷键 进口联合收割机 结构锦标赛:可识别{ var id=UUID().uuistring 变量名称:String var位置:String=“特许经营” 变量日期:日期=日期() } #如果调试 var blankTournament=锦标赛(名称:“”) var testTournamentData=[ 锦标赛(名称:“锦标赛1”), 锦标赛(名称:“锦标赛2”), 锦标赛(名称:“锦标赛3”), ] #恩迪夫 结构ContentView:View{ @ObservedObject变量tournamentListVM=tournamentListVM() var body:一些观点{ 导航视图{ VStack{ 列表(tournamentListVM.tournamentCellVMs){tournamentCellVM在 导航链接( 目的地:TournamentDetails(锦标赛:tournamentCellVM.tournament), 标签:{TournamentCell(tournamentCellVM:tournamentCellVM)} )}} .navigationTitle(“二合一(\(tournamentListVM.tournamentCellVMs.count))) .航海术语( 尾随:导航链接( 目的地:TournamentDetails(addingNewTournament:true)) {Image(系统名:“plus”)} )}}} 结构TournamentCell:视图{ @ObservedObject变量tournamentCellVM:tournamentCellVM var body:一些观点{ VStack(对齐:。前导){ 文本(tournamentCellVM.tournament.name) } } } 结构锦标赛详细信息:查看{ @环境(\.presentationMode)var presentationMode//用于关闭视图 @ObservedObject变量tournamentListVM=tournamentListVM() @状态变量锦标赛=空白锦标赛 var addingNewTournament:Bool=false 变量索引:Int?//更新现有记录时需要 var body:一些观点{ 形式{ 节(标题:文本(“锦标赛信息”)){ TextField(“Name”,text:$tournament.Name) TextField(“位置”,文本:$tournament.Location) 日期选择器(选择:$Tornament.date,displayedComponents:.date){Text(“日期”)} } 第{节按钮(操作:{ 如果添加newTournament{tournamentListVM.createTournament(tournament)} else{tournamentListVM.updateTournament(锦标赛)} presentationMode.wrappedValue.Disclease() }){Text(addingNewTournament?“保存锦标赛”:“更新锦标赛”)} }}}} 类TournamentListVM:ObserveObject{ @已发布的var tournamentCellVMs=[TournamentCellVM]() private var cancelables=Set() init(){ self.tournamentCellVMs=testTournamentData.map{中的锦标赛 TournamentCellVM(锦标赛:锦标赛) } } func createTournament(uuTournament:tournament){ 打印(tournamentCellVMs.count) append(TournamentCellVM(锦标赛:锦标赛)) 打印(tournamentCellVMs.count) } func updateTournament(uu锦标赛:锦标赛){ } } 类TournamentCellVM:可观察对象,可识别{ @公开赛:锦标赛 var id=“” private var cancelables=Set() 初始(锦标赛:锦标赛){ 自我锦标赛 美元锦标赛 .map{锦标赛中的锦标赛.id} .assign(到:\.id,在:self上) .store(在:&可取消项中) }}
当我准备发布我的问题时,所以向我指出了其他可能类似的问题。我在这里发布我的解决方案,作为我自己和他人的资源

在那篇文章中,我了解到如果列表动态变化,那么您必须使用
.index

以下是我所做的更改,现在可以使用了:

  • 在结构内容视图中:
  • 变成

    List {
        ForEach (tournamentListVM.tournamentCellVMs.indices, id: \.self) { index in
            NavigationLink(
                destination: TournamentDetails(tournamentListVM: tournamentListVM, tournament: tournamentListVM.tournamentCellVMs[index].tournament),
                label: { TournamentCell(tournamentCellVM: tournamentListVM.tournamentCellVMs[index]) }
    )}}}
    .navigationTitle("All in Two (\(tournamentListVM.tournamentCellVMs.count))")
    .navigationBarItems(
        trailing: NavigationLink(
        destination: TournamentDetails(tournamentListVM: tournamentListVM, addingNewTournament: true))
            { Image(systemName: "plus") }
    )}}}
    
  • struct TournamentDetails
    中:
  • @ObservedObject var tournamentListVM=tournamentListVM()

    变成

    List {
        ForEach (tournamentListVM.tournamentCellVMs.indices, id: \.self) { index in
            NavigationLink(
                destination: TournamentDetails(tournamentListVM: tournamentListVM, tournament: tournamentListVM.tournamentCellVMs[index].tournament),
                label: { TournamentCell(tournamentCellVM: tournamentListVM.tournamentCellVMs[index]) }
    )}}}
    .navigationTitle("All in Two (\(tournamentListVM.tournamentCellVMs.count))")
    .navigationBarItems(
        trailing: NavigationLink(
        destination: TournamentDetails(tournamentListVM: tournamentListVM, addingNewTournament: true))
            { Image(systemName: "plus") }
    )}}}
    
    @ObservedObject var tournamentListVM:tournamentListVM

  • class TournamentListVM中
  • @Published var tournamentCellVMs=[TournamentCellVM]()

    变成

    List {
        ForEach (tournamentListVM.tournamentCellVMs.indices, id: \.self) { index in
            NavigationLink(
                destination: TournamentDetails(tournamentListVM: tournamentListVM, tournament: tournamentListVM.tournamentCellVMs[index].tournament),
                label: { TournamentCell(tournamentCellVM: tournamentListVM.tournamentCellVMs[index]) }
    )}}}
    .navigationTitle("All in Two (\(tournamentListVM.tournamentCellVMs.count))")
    .navigationBarItems(
        trailing: NavigationLink(
        destination: TournamentDetails(tournamentListVM: tournamentListVM, addingNewTournament: true))
            { Image(systemName: "plus") }
    )}}}
    
    @Published var tournamentCellVMs:[TournamentCellVM]

    就这样。而且它工作得很好