Post not yet marked as solved
How secure storing the data using SwiftData? What encryption mechanism is it used to store data? Our project has a requirement to shore data using AES 256 encryption.
Post not yet marked as solved
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?
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
Post not yet marked as solved
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?
Post not yet marked as solved
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")
}
}
}
}
Post not yet marked as solved
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)
Post not yet marked as solved
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?
Post not yet marked as solved
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)
Post not yet marked as solved
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?
Post not yet marked as solved
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?
Post not yet marked as solved
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