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

Swift项目预览点击保存Recipe崩溃,模拟器正常求助

问题:SwiftData预览保存崩溃,模拟器正常

点击「保存食谱(Save Recipe)」时预览崩溃,但模拟器运行时保存功能正常。修改Model将ingredient和amount从单个数组拆分为两个独立数组后出现此问题,已确认两个数组长度始终匹配。


视图代码

import SwiftUI
import SwiftData

struct NewRecipeView: View {
    @Binding var isPresented: Bool
    @Query(sort: \Recipe.title) var recipes: [Recipe]
    @Environment(\.modelContext) private var modelContext
    @State private var recipeTitle: String = ""
    @State private var amount: [String] = [""]
    @State private var ingredient: [String] = [""]
    @State private var steps: [String] = ["Schritt 1:"]
    @State private var showRecipeOverview = false
    
    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Name des Rezeptes")) {
                    TextField("Gib einen Namen ein", text: $recipeTitle)
                }
                
                Section(header: Text("Zutaten")) {
                    ForEach(amount.indices, id: \.self) { index in
                        HStack {
                            TextField("Menge", text: Binding(
                                get: { self.amount[index] },
                                set: { self.amount[index] = $0 }
                            ))
                            .frame(width: 80)
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                            
                            TextField("Zutat", text: Binding(
                                get: { self.ingredient[index] },
                                set: { self.ingredient[index] = $0 }
                            ))
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                        }
                    }
                    Button(action: addIngredient) {
                        Text("Weitere Zutat")
                    }
                }
                
                Section(header: Text("Schritte")) {
                    ForEach(steps.indices, id: \.self) { index in
                        ZStack(alignment: .topLeading) {
                            TextEditor(text: Binding(
                                get: { self.steps[index] },
                                set: { self.steps[index] = $0 }
                            ))
                            .frame(height: 150)
                        }
                    }
                    Button(action: addStep) {
                        Text("Weiteren Schritt hinzufügen")
                    }
                }
                Button(action: saveRecipe) {
                    Text("Rezept speichern")
                        .frame(maxWidth: .infinity, alignment: .center)
                }
                .padding()
                .sheet(isPresented: $showRecipeOverview) {
                    RecipeOverview()
                }
            }
            .navigationTitle("Neues Rezept")
        }
    }
    
    func addIngredient() {
        ingredient.append("")
        amount.append("")
    }
    
    func addStep() {
        steps.append("Schritt \(steps.count + 1):")
    }
    
    
    func saveRecipe() {
        print("Amount: \(amount)")
        print("Ingredients: \(ingredient)")
        let newRecipe = Recipe(title: recipeTitle, amount:amount, ingredients: ingredient, steps: steps)
         modelContext.insert(newRecipe)
         isPresented = false
        
    }
}

#Preview {
    NewRecipeView(isPresented: .constant(false))
        .modelContainer(for: Recipe.self)
}

Model代码

import Foundation
import SwiftData

@Model
class Recipe {
    var id = UUID().uuidString
    var title: String
    var amount: [String]
    var ingredients: [String]
    var steps: [String]
    
    init(title: String, amount: [String], ingredients: [String], steps: [String]) {
        self.title = title
        self.amount = amount
        self.ingredients = ingredients
        self.steps = steps
    }
}

调试信息

打印显示两个数组长度始终一致:

Amount: ["5oz", "5", ""]
Ingredients: ["Cheese", "Burger", ""]

解决方案

核心原因

SwiftData预览容器的模型架构缓存未更新。修改Model结构后,预览仍在使用旧的模型schema,写入新结构数据时引发崩溃,而模拟器会重新生成容器,因此不受影响。

修复步骤

  1. 修改预览代码,使用内存临时存储:
    替换原预览代码为以下内容,避免缓存的旧模型干扰:
    #Preview {
        do {
            let container = try ModelContainer(for: Recipe.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true))
            return NewRecipeView(isPresented: .constant(false))
                .modelContainer(container)
        } catch {
            return Text("Failed to create model container: \(error.localizedDescription)")
        }
    }
    
  2. 清理项目缓存:
    执行Product > Clean Build Folder,重启Xcode后重新加载预览。

额外优化

可以在保存时过滤空的食材条目,避免存储无效数据:

func saveRecipe() {
    // 过滤掉空的食材对(至少一项不为空才保留)
    let validPairs = zip(amount, ingredient).filter { !$0.0.isEmpty || !$0.1.isEmpty }
    let validAmounts = validPairs.map { $0.0 }
    let validIngredients = validPairs.map { $0.1 }
    
    let newRecipe = Recipe(title: recipeTitle, amount: validAmounts, ingredients: validIngredients, steps: steps)
    modelContext.insert(newRecipe)
    isPresented = false
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:18:09