contributors |
---|
Jeehut |
import SwiftData
and markclass
with@Model
to create schema- Use
@Attribute(.unique)
to make field unique, if already exists, then "upsert" will happen, updating existing data (insert -> update) - Uniqueness available for primitive value types: Numeric, String, UUID – can also decorate relationships
- Renaming variables without any attributes generates new properties and deletes old
- To keep data but rename field, specify
@Attribute(originalName: "oldName")
to map data @Attribute
also supports storing large data externally, supplying support forTransformable
s, integrate with Spotlight, modify hash- SwiftData implicitly discoveres (inverse) relationships between models for fields like
var bucketList: [BucketListItem]? = []
- The default deletion strategy for relationships when no annotations provided is "nil out"
- To delete relationships alongside, specify attribute
@Relationship(.cascade)
explicitly @Relationship
modifier also supportsoriginalName
and constraints ontoMany
for min/max count constraints, plus modifying hash- To exclude a stored property from the schema, annotate it with
@Transient
– a default value is required
- Define an enum conforming to
VersionedSchema
and put your models inside the enum (used as a namespace) - Order versions with
SchemaMigrationPlan
- Define migration stage: Lightweight (no code required), Custom (code needed)
- Provide
migrationPlan
toModelContainer
Example for VersionedSchema
:
enum SampleTripsSchemaV2: VersionedSchema {
static var models: [any PersistentModel.Type] {
[Trip.self, BucketListItem.self, LivingAccommodation.self]
}
@Model
final class Trip {
@Attribute(.unique)
var name: String
var destination: String
var start_date: Date
var end_date: Date
var bucketList: [BucketListItem]? = []
var livingAccommodation: LivingAccommodation?
}
// other models
}
Example for SchemaMigrationPlan
:
enum SampleTripsMigrationPlan: SchemaMigrationPlan {
static var schemas: [any VersionedSchema.Type] {
[SampleTripsSchemaV1.self, SampleTripsSchemaV2.self, SampleTripsSchemaV3.self]
}
static var stages: [MigrationStage] { [migrateV1toV2] }
static let migrateVltoV2 = MigrationStage.custom(
fromVersion: SampleTripsSchemaV1.self,
toVersion: SampleTripsSchemaV2.self,
willMigrate: { context in
let trips = try? context.fetch(FetchDescriptor<SampleTripsSchemaV1.Trip> ())
// De-duplicate Trip instances here..
try? context.save ()
},
didMigrate: nil
)
}
Example for passing migration plan to model container:
struct TripsApp: App {
let container = ModelContainer(for: Trip.self, migrationPlan: SampleTripsMigrationPlan.self)
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(container)
}
}