Мое приложение аварийно завершает работу при запуске при попытке создать SwiftData ModelContainer после создания состояния миграции из V1 в V2.
Вот сообщение об ошибке, которое я получаю: Тема 1: Неустранимая ошибка: не удалось выполнить создать ModelContainer для обуви: операцию не удалось завершить. (Ошибка SwiftData.SwiftDataError 1.)
Что изменилось в моей единственной модели с версии V1 на версию V2?
Я добавил новое свойство под названием defaultRunTypes: [RunType] где RunType — это перечисление с 5 различными вариантами.
Модель V1 имеет только свойство isDefaultShoe: Bool, и я хочу расширить функциональность, чтобы иметь несколько значений по умолчанию для разных типов run.
Теперь немного кода.
Вот как я создаю контейнер:
typealias Shoe = ShoesSchemaV2.Shoe
final class ShoesStore {
static let container = {
let container: ModelContainer
do {
container = try ModelContainer(for: Shoe.self, migrationPlan: ShoesMigrationPlan.self)
} catch {
fatalError("Failed to create ModelContainer for Shoe: \(error.localizedDescription)")
}
return container
}()
}
Это план миграции.
enum ShoesMigrationPlan: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] {
[ShoesSchemaV1.self, ShoesSchemaV2.self]
}
static var stages: [MigrationStage] {
[migrateV1toV2]
}
static let migrateV1toV2 = MigrationStage.custom(
fromVersion: ShoesSchemaV1.self,
toVersion: ShoesSchemaV2.self,
willMigrate: { context in
print("Migration: willMigrae")
let v1Shoes = try? context.fetch(FetchDescriptor())
for v1Shoe in v1Shoes ?? [] {
print("Migration: V1 Shoe: \(v1Shoe.brand) \(v1Shoe.model) - isDefaultShoe = \(v1Shoe.isDefaultShoe)")
let v2Shoe = ShoesSchemaV2.Shoe(
id: v1Shoe.id,
image: v1Shoe.image,
brand: v1Shoe.brand,
model: v1Shoe.model,
nickname: v1Shoe.nickname,
lifespanDistance: v1Shoe.lifespanDistance,
aquisitionDate: v1Shoe.aquisitionDate,
totalDistance: v1Shoe.totalDistance,
totalDuration: v1Shoe.totalDuration,
lastActivityDate: v1Shoe.lastActivityDate,
isRetired: v1Shoe.isRetired,
retireDate: v1Shoe.retireDate,
isDefaultShoe: v1Shoe.isDefaultShoe,
defaultRunTypes: v1Shoe.isDefaultShoe ? [.daily] : [], // this is the newly added property
workouts: v1Shoe.workouts,
personalBests: v1Shoe.personalBests,
totalRuns: v1Shoe.totalRuns
)
print("Migration: V2 shoe created: \(v1Shoe.brand) \(v1Shoe.model) - defaultRunTypes: \(v2Shoe.defaultRunTypes.count)")
context.insert(v2Shoe)
context.delete(v1Shoe)
}
try? context.save()
},
didMigrate: { context in
print("Migration: didMigrate")
let v2Shoes = try? context.fetch(FetchDescriptor())
for v2Shoe in v2Shoes ?? [] {
print("Migration: V2 shoe: \(v2Shoe.brand) \(v2Shoe.model) - defaultRunTypes: \(v2Shoe.defaultRunTypes.count)")
}
}
)
}
При миграции у меня есть следующий вывод на консоль. willMigrate выполняется, но не DidMigrate
Migration: willMigrate
Migration: V1 Shoe: Adidas Adizero Boston 12 - isDefaultShoe = true
Migration: V2 shoe created: Adidas Adizero Boston 12 - defaultRunTypes: 1
Migration: V1 Shoe: Nike Pegasus Turbo - isDefaultShoe = false
Migration: V2 shoe created: Nike Pegasus Turbo - defaultRunTypes: 0
Migration: V1 Shoe: Nike Zoomfly 5 - isDefaultShoe = false
Migration: V2 shoe created: Nike Zoomfly 5 - defaultRunTypes: 0
Migration: V1 Shoe: Nike Vaporfly 3 - isDefaultShoe = false
Migration: V2 shoe created: Nike Vaporfly 3 - defaultRunTypes: 0
Migration: V1 Shoe: Hoka Speedgoat 6 - isDefaultShoe = false
Migration: V2 shoe created: Hoka Speedgoat 6 - defaultRunTypes: 0
ShoeHealth/ShoesStore.swift:21: Fatal error: Failed to create ModelContainer for Shoe: The operation couldn’t be completed. (SwiftData.SwiftDataError error 1.)
Я не знаю, что здесь происходит, поскольку это моя первая миграция. Является ли способ создания ModelContainer проблемой (он статический — я делаю это, потому что мне также нужен доступ к нему в WidgetKit)?
Вот как я получаю доступ это в AppIntentTimelineProvider:
struct MediumShoeStatsTimelineProvider: AppIntentTimelineProvider {
let modelContext = ModelContext(ShoesStore.container)
// rest of the code, where I am using the modelContext to fetch models
}
Позднее редактирование:
Я попробовал перейти с пользовательского MigrationState на облегченный, и это работает. За исключением того факта, что defaultRunTypes пуст для всех ботинок, как и ожидалось, поскольку это значение по умолчанию.
Поэтому способ создания пользовательского MigrationState, я думаю, неправильный.
static let migrateV1toV2 = MigrationStage.lightweight(fromVersion: ShoesSchemaV1.self, toVersion: ShoesSchemaV2.self)
Подробнее здесь: https://stackoverflow.com/questions/793 ... -migrating
SwiftData: не удалось создать ModelContainer при миграции ⇐ IOS
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение