SwiftData аварийно завершает работу при инициализации

Ниже приведен минимальный код, вызывающий сбой. Чего я хочу достичь: передать представление AchievementB по умолчанию, а затем изменить (на основе ввода пользователя) и вставить в достижения.

обновление: после нескольких попыток кажется, что я не могу инициализировать объект до появления представления, но я не знаю, почему.

import SwiftData
import SwiftUI

@Model
class AchievementB: Identifiable {
  let id: UUID = UUID()

  init(id: UUID = UUID()) {
      self.id = id
  }
}

struct AchievementView: View {
  @State var options: AchievementB

  @Environment(\.modelContext) private var modelContext
  @Query var achievements: [AchievementB]
  
  var body: some View {
    Text("hello")
  }
}

#Preview {
  AchievementView(options: AchievementB())
    .modelContainer(for: AchievementB.self)
}

Итак, вы запускаете это в Xcode Previews?

Sweeper 28.05.2024 09:41

это верно

user1385809 28.05.2024 09:41

У меня это не крашится. Правильно ли вы настроили ModelContainer для самого приложения?

Joakim Danielson 28.05.2024 10:17

это весь код, который у меня есть. о какой настройке вы говорите?

user1385809 28.05.2024 10:25

В коде вашего приложения в <имя моего приложения>.swift вы также должны добавить модификатор .modelContainer в WindowGroup.

Joakim Danielson 28.05.2024 10:28

для этого он у меня есть: WindowGroup { AchievementView(options: AchievementB()) } .modelContainer(for: [AchievementB.self])

user1385809 28.05.2024 10:40

Возможно, вам просто нужно очистить папку сборки или что-то в этом роде, потому что на iOS 17.5 (Xcode 15.4) ваш код работает нормально, как и на моем компьютере.

Joakim Danielson 28.05.2024 11:12
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем коде объект AchievementB создается до существования контейнера модели. AchievementB() выполняется первым, перед модификатором .modelContainer(for: ...), который создает контейнер модели.

Прежде чем создавать какие-либо объекты @Model, вам следует сначала создать контейнер модели, поскольку для работы свойств объектам @Model необходим контейнер модели. Когда вы получаете/устанавливаете свойство объекта @Model, фактическое чтение и запись данных делегируется контейнеру модели.

Сначала вам следует вручную создать ModelContainer, а затем добавить его в представление, используя другую перегрузку модификатора modelContainer.

#Preview {
    let config = ModelConfiguration(isStoredInMemoryOnly: true)
    let container = try! ModelContainer(for: AchievementB.self, configurations: config)
    return AchievementView(options: AchievementB())
        .modelContainer(container)
}

Обратите внимание, что вам необходимо явно указать return, поскольку #Preview не является построителем представлений.

Примечание: options не должно быть @State, если вы собираетесь передать ему что-то. Это должен быть обычный let/var или @Bindable, если вы хотите получить от него Binding.

В Xcode 15.4 это, похоже, не нужно, и наличие только AchievementView(options: AchievementB()).modelContainer(for: AchievementB.self, inMemory: true) в макросе #Preview работает нормально.

Joakim Danielson 28.05.2024 11:16

@JoakimDanielson Ах, это интересно. Я (и, вероятно, ОП тоже) использую Xcode 15.3.

Sweeper 28.05.2024 11:19

Другие вопросы по теме