Post not yet marked as solved
@Model class AModel {
@Attribute(.unique) var id:String
var date:Date
var b:[BModel]
init() {
self.id = UUID().uuidString
self.date = Date()
self.b = []
}
}
@Model class BModel {
@Attribute(.unique) var id:String
var date:Date
init() {
self.id = UUID().uuidString
self.date = Date()
}
}
struct MainView: View {
@Environment(\.modelContext) private var db
@State private var a:AModel = AModel()
var body: some View {
VStack {
}
.onAppear {
a.b.append(BModel())
print(a.b)
}
}
}
// CRASH :
@Model class AModel {
@Attribute(.unique) var id:String
var date:Date
var b:[BModel]
/**
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
{
get {
_$observationRegistrar.access(self, keyPath: \.b)
return self.getValue(for: \.b)
}
set {
_$observationRegistrar.withMutation(of: self, keyPath: \.b) {
self.setValue(for: \.b, to: newValue)
}
}
}
*/
init() {
self.id = UUID().uuidString
self.date = Date()
self.b = []
}
}
@Model class BModel {
@Attribute(.unique) var id:String
var date:Date
init() {
self.id = UUID().uuidString
self.date = Date()
}
}
I'm converting my app to use SwiftData. I have a class called MergeRequest which everytime I insert it into the modelContext it fails with the following error:
CoreData: error: CoreData: error: Row (pk = 1) for entity 'MergeRequest' is missing mandatory text data for property 'id'
CoreData: error: CoreData: error: Row (pk = 2) for entity 'MergeRequest' is missing mandatory text data for property 'id'
(... repeated for each inserted item)
When I print the id before inserting the class does have a coredata generated id.
PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata:///MergeRequest/t5B3316FC-DBE0-4440-88E5-8EDFBA7E856A3), implementation: SwiftData.PersistentIdentifierImplementation)
This is where I insert the model: https://github.com/StefKors/GitLab/blob/cb4c1ef6dec616d5ac146d712658496095c82243/Shared/UserInterface/UserInterface.swift#L137
And this is the full model class: https://github.com/StefKors/GitLab/blob/cb4c1ef6dec616d5ac146d712658496095c82243/Shared/UserInterface/SwiftData/MergeRequest.swift
What I don't get is why does this error happen while it does have an id. Is there some debugging I can do to get more information?
Post not yet marked as solved
The Sendable documentation says we can mark reference types as Sendable if they "internally manage access to their state."
Adding Sendable conformance to my SwiftData classes silences warnings such as the following: "Non-sendable type '[Item]' returned by implicitly asynchronous call to nonisolated function cannot cross actor boundary"
@Model final class Item: Sendable {
var sampleProperty = ""
}
My understanding is that the compiler would complain if adding explicit Sendable conformance to a swift data model was breaking concurrency rules, but I wanted to check with the community to see what everyone thinks.
Best,
Taylor
Post not yet marked as solved
Does SwiftData support UIImage as in CoreData specified here: https://www.swiftdevjournal.com/saving-images-in-core-data/ If it does, how to specify that in the @Model schema, especially using external storage to save the image in a separate file. Thanks.
Post not yet marked as solved
I just installed Xcode beta 6 and tried compiling the SwiftData sample app. It fails with a couple of dozen compile errors. Clearly this must have worked for WWDC23 so what's gone wrong?
The following says type 'Card' does not conform to protocol 'PersistentModel'
@Model
final class Card: PersistentModel {
This seems pretty basic.
Any suggestions
I tried coding along with the WWDC23 'Dive Deeper into SwiftData' video but can't get the sample code to compile.
For example the Card class fails with lots of errors associated with @Model. The first of these is: Type 'Card' does not conform to protocol 'PersistentModel'
import SwiftUI
import SwiftData
@Model
final class Card {
var front: String
var back: String
var creationDate: Date
init(front: String, back: String, creationDate: Date = .now) {
self.front = front
self.back = back
self.creationDate = creationDate
}
}
On the other hand the following stand alone code (in it's own project) compiles without error. So I am confused and a little fed up with Apple publishing sample code that doesn't compile.
import SwiftData
@Model
final class Card {
var front: String
var back: String
var creationDate: Date
init(front: String, back: String, creationDate: Date = .now) {
self.front = front
self.back = back
self.creationDate = creationDate
}
}
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
}
}
#Preview {
ContentView()
}
Post not yet marked as solved
There is a new Relationship macro in Xcode Beta 6. The macro includes two new arguments: minimumModelCount and maximumModelCount. I wonder if anyone knows what these values are for and if there is another change under the hood.
Relationship(
_ options: PropertyOptions...,
deleteRule: Schema.Relationship.DeleteRule = .nullify,
minimumModelCount: Int? = 0,
maximumModelCount: Int? = 0,
originalName: String? = nil,
inverse: AnyKeyPath? = nil,
hashModifier: String? = nil
)
re: the SwiftData session "Create an app with SwifData" (https://developer.apple.com/videos/play/wwdc2023/10154)
I corrected the @MainActor issue, but it seems to only work with the main ContentView and not other views.
I get the following error for TripListItem for example :
failed to find a currently active container for Trip
Post not yet marked as solved
Hi, I get this error Thread 1: Fatal error: Illegal attempt to use a nil as an Attribute - type + CustomType when trying to use SwiftData on one of my main views, I wasn't seeing this error when I was working with other data types but some reason this started happening all of a sudden. Any clues as to what it might be?
Post not yet marked as solved
I have two models a Person and a Possession
the Person model has a one to many relationship to the Possession model.
meaning each possession can only have one person but a person can have multiple possessions.
I have set my model like the following
Person:
@Model
class Person {
@Attribute(.unique)
let personID: String
@Relationship(.cascade, inverse: \Possession.person)
var possetions: [Possession]?
init(id: String, possessions: [Possession]) {
self.personID = id
self.possetions = possessions
}
}
Possession:
@Model
class Possession {
@Attribute(.unique)
let id: String
let name: String?
var person: Person?
init(id: String, name: String, person: Person) {
self.id = id
self.name = name
self.person = person
}
}
If i set a breakpoint i see that all the posessions are loaded into the memory this is something i do not want to happen.
In Core Data we get a relationship fault however, i am not seeing the same behavior in SwiftData.
here's how my view is implemented
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@EnvironmentObject private var navigationStore: NavigationStore
@Query() private var people: [Person]
var body: some View {
List {
ForEach(people) { person in
NavigationLink(value: person) {
VStack {
Text(person.personID)
}
}
.swipeActions {
Button("Delete") {
modelContext.delete(person)
}
}
}
}
.toolbar(content: {
Button("Add") {
let newPErson = Person(id: UUID().uuidString, possessions: [])
modelContext.insert(newPErson)
do {
try modelContext.save()
} catch {
assertionFailure("\(error)")
}
}
})
.navigationDestination(for: Person.self) { person in
Text("hello")
}
}
}
at the launch i do not want posessions to be loaded into the memory. I want them loaded when they are being used.
Post not yet marked as solved
Hi all,
I am trying to render my SwiftUI views that uses SwiftData classes using sample data using the approach shown in the example code of wwdc2023-10196:
@MainActor #Preview {
TripsWidgetEntryView()
.modelContainer(PreviewSampleData.container)
}
Unfortunately this seems no longer valid.
Indeed I get this error:
I then tried to remove the @MainActor as suggested, but the error in then moved to another level:
What do you suggest to be the best approach to have back my preview working?
I am using Xcode Beta 4 - 15A5195m
Post not yet marked as solved
I am getting the following error on this line of code
@Query(sort: \.id, order: .reverse) private var artList: [ArtInventory]
Cannot infer key path type from context; consider explicitly specifying a root type
So, I select fix and then the line of code then look like this
@Query(sort: \<#Root#>.id, order: .reverse) private var artList: [ArtInventory]
with this error
Invalid component of Swift key path
Some seems to have changed with the @Query macro in beta 5, which now needs a root type, but not sure how to proceed.
Any ideas how to fix?
Post not yet marked as solved
Anyone know the SwiftData equivalet of the CoreData lifecycle methods. and how do we override them or do something similar? eg:
awakeFromInsert()
willSave()
didSave()
willTurnIntoFault()
prepareForDeletion()
Post not yet marked as solved
I've noticed when using @Model instead of @Observable that it bumps the CPU-usage of the app with 10%, since I'm reading values on every frame of render. This seems to cause a deep lookup. Is there a way to read the objects/attributes in memory somehow?
Post not yet marked as solved
I set my active schema to SwiftDataCardSampleEnd, open ContentView.swift, and bring up the Canvas. When I click the little refresh button I get the follow error from Canvas:
== DATE:
Friday, July 14, 2023 at 9:02:26 AM Eastern Daylight Time
2023-07-14T13:02:26Z
== PREVIEW UPDATE ERROR:
SchemeBuildError: Failed to build the scheme ”SwiftDataFlashCardSampleEnd”
linker command failed with exit code 1 (use -v to see invocation)
Link SwiftDataFlashCardSample (arm64):
ld: Undefined symbols:
unsafeMutableAddressor of self #1 : SwiftDataFlashCardSample.Card in SwiftDataFlashCardSample.Card.creationDate.init : Foundation.Date, referenced from:
SwiftDataFlashCardSample.Card.creationDate.init : Foundation.Date in Card.o
unsafeMutableAddressor of self #1 : SwiftDataFlashCardSample.Card in SwiftDataFlashCardSample.Card.back.init : Swift.String, referenced from:
SwiftDataFlashCardSample.Card.back.init : Swift.String in Card.o
unsafeMutableAddressor of self #1 : SwiftDataFlashCardSample.Card in SwiftDataFlashCardSample.Card.front.init : Swift.String, referenced from:
SwiftDataFlashCardSample.Card.front.init : Swift.String in Card.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've made a similar preview in another project where I define a model and I try to use that model in a SwiftUI Canvas preview. I get a very similar error. Basically Canvas is saying it can't find the symbols for the properties on the type.
Is there something I'm missing here? Some hidden build setting I need to flip. Or is this just busted?
What is the difference between swiftdata and coredata? I am coding by integrating coreda and icloud. As introduced at wwdc, I heard that it can be used more easily in xcode. However, for me who has to sell it tomorrow, the stability of swiftdata after the official release of ios17 in the future is low, and scalability and modification are difficult. If it's difficult, it's a lot of trouble. And the most important thing, is there any difference from coredata by using swiftdata in the experience of my valuable customers who use my program? I'm well aware that everyone is learning and discussing. Thank you for sharing your experience.
Post not yet marked as solved
In the WWDC presentations, it was mentioned that you could have multiple modelContexts within one modelContainer. Does anyone know of any examples of a project with multiple modelContexts?
Specifically, I'm wondering how you distinguish between the two different modelContexts when doing things like @Query. I'd like to keep different sets of data in separate modelContexts and only Query the one that I want to pull from for a particular view.
Thanks in advance!
Hi all,
Has anyone stumbled upon the SwiftData equivalent of @SectionedFetchRequest? Is there a way to do it with @Query? I'll keep going through the documentation but if anyone has an answer, it would be much appreciated!!
Thank you.
When trying to delete the element from my list, I always got error in my model.
get {
_$observationRegistrar.access(self, keyPath: \.id)
return self.getValue(for: \.id) <-- ERROR: Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1a949aefc)
}
Because I am new in development, I don't know how to solve it.
Overview
I have 2 models: Deparment and Student
Each Department can contain multiple students
Each Student can only be in one Department
I have DepartmentList, tapping on the department should take it to the StudentList which lists all students in the department
Problem
When I use Query in StudentList to filter only students for a specific department id, no students are shown.
Questions:
What should I do to list the students in a department? (see complete code below).
let filter = #Predicate<Student> { student in
student.department?.id == departmentID
}
let query = Query(filter: filter, sort: \.name)
_students = query
Complete code
App
@main
struct SchoolApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: [Department.self, Student.self])
}
}
Department
import Foundation
import SwiftData
@Model
class Department {
var id: UUID
var name: String
var students: [Student]
init(
id: UUID,
name: String,
students: [Student] = []
) {
self.id = id
self.name = name
self.students = students
}
}
Student
import Foundation
import SwiftData
@Model
class Student {
var id: UUID
var name: String
@Relationship(inverse: \Department.students)
var department: Department?
init(
id: UUID,
name: String,
department: Department? = nil
) {
self.id = id
self.name = name
self.department = department
}
}
ContentView
import SwiftUI
struct ContentView: View {
@State private var selectedDepartment: Department?
var body: some View {
NavigationSplitView {
DepartmentList(selectedDepartment: $selectedDepartment)
} detail: {
if let department = selectedDepartment {
StudentList(department: department)
} else {
Text("no department selected")
}
}
.task {
printStoreFilePath()
}
}
private func printStoreFilePath() {
let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
if let path = urls.map({ $0.path(percentEncoded: false) }).first {
print("Storage: \(path)")
}
}
}
DepartmentList
import SwiftUI
import SwiftData
struct DepartmentList: View {
@Binding
var selectedDepartment: Department?
@Query(sort: \.name)
private var departments: [Department]
@Environment(\.modelContext)
private var modelContext
var body: some View {
List(selection: $selectedDepartment) {
ForEach(departments) { department in
NavigationLink(value: department) {
Text(department.name)
}
}
}
.toolbar {
ToolbarItem {
Button {
addDepartment()
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
private func addDepartment() {
guard let index = (1000..<10000).randomElement() else {
return
}
let department = Department(id: UUID(), name: "Department \(index)")
modelContext.insert(department)
}
}
StudentList
import SwiftUI
import SwiftData
struct StudentList: View {
var department: Department
@Query
private var students: [Student]
@Environment(\.modelContext)
private var modelContext
init(department: Department) {
self.department = department
let departmentID = department.id
let filter = #Predicate<Student> { student in
student.department?.id == departmentID
}
let query = Query(filter: filter, sort: \.name)
_students = query
}
var body: some View {
List {
ForEach(students) { student in
Text(student.name)
}
}
.toolbar {
ToolbarItem {
Button {
addStudent()
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
private func addStudent() {
guard let index = (1000..<10000).randomElement() else {
return
}
let student = Student(
id: UUID(),
name: "Student \(index)",
department: department
)
modelContext.insert(student)
}
}