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,写入新结构数据时引发崩溃,而模拟器会重新生成容器,因此不受影响。
修复步骤
- 修改预览代码,使用内存临时存储:
替换原预览代码为以下内容,避免缓存的旧模型干扰:#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)") } } - 清理项目缓存:
执行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
相关产品推荐
相关产品推荐

