首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >为什么在我的ViewModel应用程序中添加了一个SwiftUI之后,我的UI没有更新呢?

为什么在我的ViewModel应用程序中添加了一个SwiftUI之后,我的UI没有更新呢?
EN

Stack Overflow用户
提问于 2021-04-30 13:35:16
回答 1查看 275关注 0票数 1

我一直在关注SwiftUI & Firebase上的Peter系列,从第1和第2部分开始,现在我正在尝试将我在那里学到的东西转换到我自己的小测试应用程序中,特别是在混合程序中添加一个ViewModel

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

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

在添加ViewModel代码之后,它几乎可以工作了。创建并添加到数组中的新元素。但是,UI没有更新,我不明白为什么不更新.

这是我的密码:

代码语言:javascript
代码运行次数:0
运行
复制
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)
}}
EN

回答 1

Stack Overflow用户

发布于 2021-04-30 14:11:06

当我准备贴出我的问题时,请告诉我其他可能类似的问题。其中一人帮助我找到了我问题的答案。我在这里把我的解决方案作为我自己和其他人的资源。

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

下面是我所做的改变,现在起作用了:

  1. struct ContentView
代码语言:javascript
代码运行次数:0
运行
复制
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") }
)}}}

变成了

代码语言:javascript
代码运行次数:0
运行
复制
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") }
)}}}
  1. struct TournamentDetails

@ObservedObject var tournamentListVM = TournamentListVM()

变成了

@ObservedObject var tournamentListVM: TournamentListVM

  1. class TournamentListVM

@Published var tournamentCellVMs = [TournamentCellVM]()

变成了

@Published var tournamentCellVMs: [TournamentCellVM]

就这样。而且效果很好。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67334880

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档