You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI:LotView在ResultView中无法显示抽签结果的问题

SwiftUI签文App ResultView无法显示抽签结果问题排查与解决

问题描述

App流程为 HomeView → PrayerView → PaymentView → ResultView:

  • 在PrayerView点击「抽签」按钮,调用drawLot()方法从Core Data抽取签文,PrayerView内的LotView可正常展示抽签结果
  • 完成PaymentView支付流程进入ResultView后,同款LotView仅显示默认空白/0值,无法呈现已抽取的签文结果

附ResultView代码:

import SwiftUI
import CoreData

struct ResultView: View {
    // 設置 ResultViewModel 的環境對象
    @ObservedObject var viewModel: ResultViewModel
    @ObservedObject var lotViewModel: LotViewModel
    @ObservedObject var prayerViewModel: PrayerViewModel
    var container: NSPersistentContainer

    
    init(container: NSPersistentContainer) {
        self.container = container
        lotViewModel = LotViewModel(container: container)
        prayerViewModel = PrayerViewModel(container: container)
        viewModel = ResultViewModel(container:container)
    }
    var body: some View {
            VStack {
                // 顯示籤詩相關屬性
                LotView(viewModel: lotViewModel)
                            
                    .padding()// 在此處添加 LotView
                                  
                // 顯示吉凶和分析內容
                Text("吉凶:\(viewModel.lotViewModel.luckLevel)")
                    .font(.headline)
                    .padding(.top, 20)
                Text("分析內容:\(lotViewModel.analysis)")
                    .font(.headline)
                    .multilineTextAlignment(.center)
                    .padding(.horizontal, 20)
                    .padding(.top, 20)
                
                // 顯示對應問題種類的屬性內容
               VStack {
                    //Text("\(viewModel.selectedCategory):")
                        //.font(.headline)
                       // .fontWeight(.bold)
                       // .padding(.top, 20)
                    
                    if viewModel.selectedCategory == "願望" {
                        Text(lotViewModel.wish)
                    } else if viewModel.selectedCategory == "疾病" {
                        Text(lotViewModel.illness)
                    } else if viewModel.selectedCategory == "盼望的人" {
                        Text(lotViewModel.person)
                    } else if viewModel.selectedCategory == "遺失物" {
                        Text(lotViewModel.lostItem)
                    } else if viewModel.selectedCategory == "搬家" {
                        Text(lotViewModel.moving)
                    } else if viewModel.selectedCategory == "蓋新居" {
                        Text(lotViewModel.newHome)
                    } else if viewModel.selectedCategory == "嫁娶" {
                        Text(lotViewModel.marriage)
                    } else if viewModel.selectedCategory == "交往" {
                        Text(lotViewModel.relationship)
                    } else if viewModel.selectedCategory == "旅行" {
                        Text(lotViewModel.travel)
                    } else if viewModel.selectedCategory == "結親緣" {
                        Text(lotViewModel.family)
                    }
                }
                .padding(.horizontal, 20)
                
                Spacer()
                
                // 點擊返回主畫面的按鈕
                /*NavigationStack{
                    VStack {
                        Button(action: {
                            viewModel.showHomeView()
                        }) {
                            Text("返回")
                                .font(.headline)
                                .foregroundColor(.white)
                                .padding()
                                .frame(maxWidth: .infinity)
                                .background(Color.blue)
                                .cornerRadius(10)
                                .padding(.horizontal, 20)
                                .padding(.bottom, 50)
                        }
                    }
                        .navigationDestination(isPresented:$viewModel.isPresentingHomeView){
                            HomeView(selectedGod: "玄天上帝", container: container)
                        }
            }*/
       }
    }
}
struct ResultView_Previews: PreviewProvider {
    static var previews: some View {
        let container = NSPersistentContainer(name: "MyAppDataModel")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error {
                fatalError("Failed to load Core Data stack: \(error)")
            }
        })
        return ResultView(container:container)     
    }
}

问题根源

ResultView的init方法中重新创建了LotViewModel、PrayerViewModel实例,而非复用PrayerView中已经执行过drawLot()的ViewModel实例。新实例处于初始状态,自然没有已抽取的签文数据。

另外代码中同时存在lotViewModel和viewModel.lotViewModel,说明数据持有不统一,进一步导致视图展示数据不一致。

解决方案

核心逻辑是跨视图传递已完成抽签的ViewModel实例,而非每次新建。

1. 修改ResultView初始化方式

移除内部创建ViewModel的代码,改为从外部传入已初始化完成的实例:

struct ResultView: View {
    @ObservedObject var viewModel: ResultViewModel
    @ObservedObject var lotViewModel: LotViewModel
    @ObservedObject var prayerViewModel: PrayerViewModel
    var container: NSPersistentContainer

    // 直接接收外部传入的ViewModel实例
    init(
        container: NSPersistentContainer,
        lotViewModel: LotViewModel,
        prayerViewModel: PrayerViewModel,
        viewModel: ResultViewModel
    ) {
        self.container = container
        self.lotViewModel = lotViewModel
        self.prayerViewModel = prayerViewModel
        self.viewModel = viewModel
    }
    
    // body代码保持不变
}

2. 跳转时传递正确的ViewModel实例

在PaymentView跳转到ResultView的位置,传入PrayerView中已执行drawLot()的LotViewModel实例:

// 假设PaymentView持有PrayerView传递过来的ViewModel引用
NavigationLink(destination: ResultView(
    container: container,
    lotViewModel: self.lotViewModel, // 复用已有实例
    prayerViewModel: self.prayerViewModel,
    viewModel: ResultViewModel(container: container)
)) {
    Text("完成支付查看结果")
}

3. 优化数据一致性(可选)

如果ResultViewModel需要依赖LotViewModel的数据,可在ResultViewModel初始化时传入LotViewModel,避免重复持有:

class ResultViewModel: ObservableObject {
    let lotViewModel: LotViewModel
    let container: NSPersistentContainer
    @Published var selectedCategory: String = ""
    
    init(container: NSPersistentContainer, lotViewModel: LotViewModel) {
        self.container = container
        self.lotViewModel = lotViewModel
    }
    
    // 其他业务逻辑
}

对应调整ResultView的初始化参数,确保数据来源统一。

关键注意事项

  • @ObservedObject实例若在视图内部新建,每次视图刷新都会重新初始化,导致数据丢失
  • 跨视图共享状态时,必须传递同一个ViewModel实例,或使用@EnvironmentObject实现全局共享(需匹配App架构)
  • 确保LotViewModel中存储签文结果的属性标记为@Published,才能触发视图响应数据更新

内容的提问来源于stack exchange,提问作者Lotloy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 06:35:12