Model your schema with SwiftData

RSS for tag

Discuss the WWDC23 Session Model your schema with SwiftData

View Session

Posts under wwdc2023-10195 tag

31 Posts
Sort by:
Post not yet marked as solved
3 Replies
1.5k Views
What is the best way to use swift data to store one off data models? For example an application state that you want to be persisted across application launches. The only examples I've seen use arrays of items which wouldn't work for having just one application state. Is it possible to query just one item?
Posted
by Ronan18.
Last updated
.
Post marked as solved
2 Replies
820 Views
Hi, given this model: @Model class OnlyName { var name: String init(name: String) { self.name = name } } I would assume that I could write a predicate like this: #Predicate<OnlyName> { $0.name == other.name }, where other is also an instance of OnlyName for example returned by an earlier fetch. Unfortunately this results in the following compiler errors: Initializer 'init(_:)' requires that 'OnlyName' conform to 'Encodable' Initializer 'init(_:)' requires that 'OnlyName' conform to 'Decodable' Any idea if this is a bug in SwiftData or if I am missing something? Cheers, Michael
Posted
by milutz.
Last updated
.
Post not yet marked as solved
0 Replies
849 Views
I'm stuck at an error EXC_BREAKPOINT (code=1, subcode=0x1a8d69a38)that is thrown in a class during initialization. The class is defined as: @Model public final class Parent { @Attribute(.unique) public var uuid: UUID /// The date specification. @Relationship(.cascade) public var dateSpec: DateSpec /// The title. public var title: Title /// The subtitle. public var subTitle: Subtitle public init(uuid: UUID, dateSpec: DateSpec, title: Title, subTitle: Subtitle) { self.uuid = uuid self.dateSpec = dateSpec self.title = title self.subTitle = subTitle } } The error is thrown in the var dateSpec property at the return self.getValue(for: \.dateSpec) call of the @PersistedProperty macro. DateSpec is defined this way: @Model public final class DateSpec { @Attribute(.unique) public var uuid: UUID /// The type of the date specification (`.point` or `.range`). public var type: DateSpecType @Relationship(.cascade) public var point: DatePoint @Relationship(.cascade) public var range: DateRange public init(uuid: UUID, type: DateSpecType = .none, point: DatePoint = .init(), range: DateRange = .init()) { self.uuid = uuid self.type = type self.point = point self.range = range } } And DatePoint is defined so: @Model public final class DatePoint { @Attribute(.unique) public var uuid: UUID public var format: String public var date: Date? public init(uuid: UUID, format: String, date: Date? = nil) { self.uuid = uuid self.format = format self.date = date } } (DateRange accordingly). So, as far as I understood the sessions, this should work. Or did I miss something? -- Edit: When taking out DatePoint and DateRange from the model, and replacing the properties by .transient wrappers that get/set the respective properties directly in DateSpec, then the error disappears. So, is the problem the cascading of the relationships between Parent and DateSpec, and DateSpec and DatePoint/DateRange?
Posted
by HardyS.
Last updated
.
Post not yet marked as solved
0 Replies
1k Views
Hi, I encountered the issue, that unless an inverse relationship is modelled, the relationship is not persisted. This can be reproduced with the sample code below: Press the "Add Person" button twice Then press the "Add group" button You now can see that the group has to member, but once you restart the app the members a gone. Once an inverse relationship is added (see commented code) the relationships are persisted. Any idea if this is intended behaviour? import SwiftData import SwiftUI // MARK: - Person - @Model class Person { var name: String // uncomment to make it work @Relationship(.nullify) var group: Group? init(name: String) { self.name = name } } // MARK: - Group - @Model class Group { var name: String // uncomment to make it work @Relationship(.nullify, inverse: \Person.group) public var members: [Person] @Relationship(.nullify) public var members: [Person] // comment to make it work init(name: String) { self.name = name } } // MARK: - SD_PrototypingApp - @main struct SD_PrototypingApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer(for: [Person.self, Group.self]) } } // MARK: - ContentView - struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var groups: [Group] @Query private var persons: [Person] var body: some View { VStack { ForEach(groups) { group in Text("\(group.name): \(group.members.count)") } ForEach(persons) { person in Text("Person: \(person.name)") } Button { assert(persons.isEmpty == false) if groups.isEmpty { let group = Group(name: "Group A") group.members = persons modelContext.insert(group) try! modelContext.save() } } label: { Text("Add a group") } .disabled(!groups.isEmpty || persons.isEmpty) Button { let person = Person(name: "Person \(Int.random(in: 0 ... 1_000_000))") modelContext.insert(person) } label: { Text("Add Person") } } } }
Posted
by milutz.
Last updated
.
Post not yet marked as solved
2 Replies
643 Views
I used Schema and MigrationPlan to initialize the Model Container. SwiftDataDemoApp.swift Then I modified the Schema and created a MigrationStage through the custom method, which was configured in the stages array of the SchemaMigrationPlan. Models.swift But when I run the app, I don't receive the willMigrate and didMigrate callbacks Xcode Version: 15.0 beta (15A5160n) MacOS: 13.3.1 (a) (22E772610a)
Posted Last updated
.
Post not yet marked as solved
3 Replies
1.4k Views
The 'unique' attribute is a really nice feature, BUT. In some of my apps, the unique identifier for an object is a combination of multiple attributes. (Example: a book title is not unique, but a combination of book title and author list is.) How do I model this with SwiftData? I cannot use @Attribute(.unique) on either the title OR the author list, but I want SwiftData to provide the same "insert or update" logic. Is this possible?
Posted Last updated
.
Post not yet marked as solved
1 Replies
958 Views
I can't find the method to create ModelContainer that appears in the video at 8: 52. The code in the video is as follows: let container = ModelContainer( for: Trip.self, migrationPlan: SampleTripsMigrationPlan.self ) This method doesn't seem to exist in Xcode15. I found other method to create ModelContainer using Schema and Schema MigrationPlan in Xcode15. public convenience init(for givenSchema: Schema, migrationPlan: (SchemaMigrationPlan.Type)? = nil, _ configurations: ModelConfiguration...) throws And I tried to create a Schema to use this method, like this: let container = try! ModelContainer(for: .init([Person.self]), migrationPlan: MigrationPlan.self) But an error occurred during runtime SwiftData/ModelContext.swift:177: Fatal error: Container does not have any data stores SwiftDataDemoApp.swift How to create a ModelContainer with [PersistentModel] and SchemaMigrationPlan ? Xcode Version: 15.0 beta (15A5160n) MacOS: 13.3.1 (a) (22E772610a)
Posted Last updated
.
Post not yet marked as solved
1 Replies
709 Views
I am watching Swiftdata videos, but so far they haven't mentioned CloudKit explicitly, and I'm not sure what is the relationship between SwiftData and Cloudkit at this time. Are these models automatically synced with Cloudkit? If that's the case, do the migration plans work for cloudkit as well?
Posted
by raspo.
Last updated
.
Post not yet marked as solved
0 Replies
337 Views
I understand that in the demo we have version 1 to 3 in the schema plan, but where does the current version live, the one with relationship decorations? And how is the current version's migration type declared or handled?
Posted
by Cormentis.
Last updated
.
Post not yet marked as solved
0 Replies
443 Views
Hello, the way I understand the schema migrations in conjunction with the originalName modifier, is that I will always need this property rapper for future migrations of my app. Is that correct? @Attribute(originalName: "start_date") var startDate: Date @Attribute(originalName: "end_date") var endDate: Date Let's say I do a V4 migration and do another change (irrelevant in this context; can be anything). Do startDate and endDate each need @Attribute(originalName: <#String>) or has SwiftData already renamed those attributes in the store and therefore I wouldn't need this anymore? Thank you! Denis
Posted
by DenisGo.
Last updated
.