Hi! I'm experimenting with SwiftData and looking for a situation where one persistentModelID might result in more than one registered model object reference delivered from a fetch from a single context. Here is an example of what I have to experiment:
import Foundation
import SwiftData
@Model class Person {
var name: String
init(name: String) {
self.name = name
}
}
func main() {
let configuration = ModelConfiguration(
isStoredInMemoryOnly: true,
allowsSave: true
)
do {
let container = try ModelContainer(
for: Person.self,
configurations: configuration
)
let context = ModelContext(container)
let person = Person(name: "John Appleseed")
context.insert(person)
let persistentModelID = person.persistentModelID
if let left: Person = context.registeredModel(for: persistentModelID),
let right: Person = context.registeredModel(for: persistentModelID) {
print(left === right) // true
}
let descriptor = FetchDescriptor<Person>(
predicate: #Predicate { person in
person.persistentModelID == persistentModelID
}
)
if let left = try context.fetch(descriptor).last,
let right = try context.fetch(descriptor).last {
print(left === right) // true
}
} catch {
print(error)
}
}
main()
This is a very simple command line app that attempts to fetch "two different" registered models… but both approaches (querying directly for persistentModelID and wrapping persistentModelID with FetchDescriptor) seem to consistently deliver objects equal by reference.
Is there any situation where I could set this code up to deliver two registered models different by reference (but equal by value)? Is this anything I have to think about or manage at an "app" level? Is this behavior documented anywhere? Thanks!
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi! I'm building an app from production Xcode_15.4.0 and I'm seeing strange behavior from the Model macro:
import SwiftData
@Model package class Person {
init() {
}
}
Building this from Xcode_15.4.0 or Swift 5.10 leads to these errors:
/var/folders/1j/0r1s_v0n4bn200kt9nkm9j5w0000gn/T/swift-generated-sources/@__swiftmacro_9MyLibrary6Person5ModelfMe_.swift:1:1: error: initializer 'init(backingData:)' must be as accessible as its enclosing type because it matches a requirement in protocol 'PersistentModel'
extension Person: SwiftData.PersistentModel {
^
/Users/rick/Desktop/MyLibrary/Sources/MyLibrary/MyLibrary.swift:3:1: note: in expansion of macro 'Model' on class 'Person' here
@Model package class Person {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/folders/1j/0r1s_v0n4bn200kt9nkm9j5w0000gn/T/swift-generated-sources/@__swiftmacro_9MyLibrary6Person5ModelfMm_.swift:19:10: note: mark the initializer as 'package' to satisfy the requirement
required init(backingData: any SwiftData.BackingData<Person>) {
^
/Users/rick/Desktop/MyLibrary/Sources/MyLibrary/MyLibrary.swift:3:1: note: in expansion of macro 'Model' on class 'Person' here
@Model package class Person {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/folders/1j/0r1s_v0n4bn200kt9nkm9j5w0000gn/T/swift-generated-sources/@__swiftmacro_9MyLibrary6Person5ModelfMe_.swift:1:1: error: property 'schemaMetadata' must be as accessible as its enclosing type because it matches a requirement in protocol 'PersistentModel'
extension Person: SwiftData.PersistentModel {
^
/Users/rick/Desktop/MyLibrary/Sources/MyLibrary/MyLibrary.swift:3:1: note: in expansion of macro 'Model' on class 'Person' here
@Model package class Person {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/folders/1j/0r1s_v0n4bn200kt9nkm9j5w0000gn/T/swift-generated-sources/@__swiftmacro_9MyLibrary6Person5ModelfMm_.swift:13:12: note: mark the static property as 'package' to satisfy the requirement
static var schemaMetadata: [SwiftData.Schema.PropertyMetadata] {
^
/Users/rick/Desktop/MyLibrary/Sources/MyLibrary/MyLibrary.swift:3:1: note: in expansion of macro 'Model' on class 'Person' here
@Model package class Person {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/folders/1j/0r1s_v0n4bn200kt9nkm9j5w0000gn/T/swift-generated-sources/@__swiftmacro_9MyLibrary6Person5ModelfMe_.swift:1:1: error: initializer 'init(backingData:)' must be as accessible as its enclosing type because it matches a requirement in protocol 'PersistentModel'
extension Person: SwiftData.PersistentModel {
^
/Users/rick/Desktop/MyLibrary/Sources/MyLibrary/MyLibrary.swift:3:1: note: in expansion of macro 'Model' on class 'Person' here
@Model package class Person {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/folders/1j/0r1s_v0n4bn200kt9nkm9j5w0000gn/T/swift-generated-sources/@__swiftmacro_9MyLibrary6Person5ModelfMm_.swift:19:10: note: mark the initializer as 'package' to satisfy the requirement
required init(backingData: any SwiftData.BackingData<Person>) {
^
/Users/rick/Desktop/MyLibrary/Sources/MyLibrary/MyLibrary.swift:3:1: note: in expansion of macro 'Model' on class 'Person' here
@Model package class Person {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/folders/1j/0r1s_v0n4bn200kt9nkm9j5w0000gn/T/swift-generated-sources/@__swiftmacro_9MyLibrary6Person5ModelfMe_.swift:1:1: error: property 'schemaMetadata' must be as accessible as its enclosing type because it matches a requirement in protocol 'PersistentModel'
extension Person: SwiftData.PersistentModel {
^
/Users/rick/Desktop/MyLibrary/Sources/MyLibrary/MyLibrary.swift:3:1: note: in expansion of macro 'Model' on class 'Person' here
@Model package class Person {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/folders/1j/0r1s_v0n4bn200kt9nkm9j5w0000gn/T/swift-generated-sources/@__swiftmacro_9MyLibrary6Person5ModelfMm_.swift:13:12: note: mark the static property as 'package' to satisfy the requirement
static var schemaMetadata: [SwiftData.Schema.PropertyMetadata] {
^
/Users/rick/Desktop/MyLibrary/Sources/MyLibrary/MyLibrary.swift:3:1: note: in expansion of macro 'Model' on class 'Person' here
@Model package class Person {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: fatalError
Building from Xcode_16_beta_4 or Swift 6.0 builds with no errors.
Is this package issue being tracked for SwiftData when building from 5.10? It looks like this is fixed from 6.0… but I would like to build this code from production Swift today.
Potential workarounds:
Mark the class as internal or public?
Use Xcode to inline the macro expansion and directly modify the broken functions with the correct access control?
Any more ideas?
My preference would be to keep this type package (while also building from 5.10). Any more workarounds (other than expanding the macro and modifying the functions myself by-hand)? Thanks!
Hi! I'm investigating some crashes that seem to be related to ModelContext.autosaveEnabled^1. I don't have a very clean repro test case at this time… but I seem to be seeing crashes when a SwiftUI app moves to the background. I am testing an app built for macOS 14.6.1. I am building from Xcode_16_beta_5.
My app is not using a mainContext. My app is building a ModelActor that is running on a background thread (off main). The modelContext inside my ModelActor is set with autosaveEnabled equal to true. The mutations on my state are not being explicitly saved (I am waiting for the system to save automatically).
My guess (so far) is that transitioning into the background from SwiftUI is kicking off some kind of logic that is specifically being tied to the main thread… but this is causing problems when my modelContext is created from a background thread. My understanding was that ModelActor could help to defend against threading problems… but this might be a different problem that I did not expect.
I am unblocked for now by turning off autosaveEnabled (and manually saving from my ModelActor). That fixes the crashes. Any more thoughts or insight about what could be causing these crashes when my app transitions into the background? Thanks!
Thread 1 Queue : com.apple.main-thread (serial)
#0 0x000000023108beb8 in ___lldb_unnamed_symbol2827 ()
#1 0x000000023108ef30 in ___lldb_unnamed_symbol2847 ()
#2 0x000000023108eca8 in ___lldb_unnamed_symbol2845 ()
#3 0x000000019bac6144 in __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ ()
#4 0x000000019bb5a3d8 in ___CFXRegistrationPost_block_invoke ()
#5 0x000000019bb5a320 in _CFXRegistrationPost ()
#6 0x000000019ba94678 in _CFXNotificationPost ()
#7 0x000000019cbb12c4 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#8 0x000000019f489408 in -[NSApplication _handleDeactivateEvent:] ()
#9 0x000000019fb24380 in -[NSApplication(NSEventRouting) sendEvent:] ()
#10 0x000000019f771d9c in -[NSApplication _handleEvent:] ()
#11 0x000000019f322020 in -[NSApplication run] ()
#12 0x000000019f2f9240 in NSApplicationMain ()
#13 0x00000001c74c73b8 in ___lldb_unnamed_symbol83060 ()
#14 0x00000001c7c30ddc in ___lldb_unnamed_symbol132917 ()
#15 0x00000001c802be0c in static SwiftUI.App.main() -> () ()
Thread 5 Queue : NSManagedObjectContext 0x6000009c38e0 (serial)
#0 0x000000019ba66f94 in constructBuffers ()
#1 0x000000019ba65e30 in _CFURLCreateWithURLString ()
#2 0x000000019bad6e7c in _CFURLComponentsCopyURLRelativeToURL ()
#3 0x000000019cbde864 in -[__NSConcreteURLComponents URL] ()
#4 0x000000019d3782f8 in -[NSURL(NSURL) initWithString:relativeToURL:encodingInvalidCharacters:] ()
#5 0x000000019cbdd4d4 in +[NSURL(NSURL) URLWithString:relativeToURL:] ()
#6 0x00000001a23feef0 in -[NSTemporaryObjectID URIRepresentation] ()
#7 0x00000002310e0878 in ___lldb_unnamed_symbol4176 ()
#8 0x00000002310ef480 in ___lldb_unnamed_symbol4401 ()
#9 0x00000002310eb6e0 in ___lldb_unnamed_symbol4385 ()
#10 0x00000002310a22b4 in ___lldb_unnamed_symbol3130 ()
#11 0x00000002310ed4e8 in ___lldb_unnamed_symbol4390 ()
#12 0x00000002310883dc in ___lldb_unnamed_symbol2799 ()
#13 0x0000000231087edc in ___lldb_unnamed_symbol2798 ()
#14 0x000000023109fd24 in ___lldb_unnamed_symbol3021 ()
#15 0x0000000231086acc in ___lldb_unnamed_symbol2784 ()
#16 0x00000001a2392144 in developerSubmittedBlockToNSManagedObjectContextPerform ()
#17 0x00000001a2392004 in -[NSManagedObjectContext performBlockAndWait:] ()
#18 0x00000002310879ac in ___lldb_unnamed_symbol2797 ()
https://github.com/ordo-one/package-benchmark/issues/264
Hi! I am seeing this error specifically when I try to run the Ordo One benchmarks package with a SwiftData context. I am not sure if there is something missing in Ordo One or if this is some kind of legit SwiftData error. My benchmarks seem to be running fine even after the error prints.
Any idea where that error might be coming from (and why I am not seeing that error when running SwiftData from other package executables)?
Hi! I'm attempting to run the Quakes Sample App^1 from macOS. I am running breakpoints and confirming the mapCameraKeyframeAnimator is being called:
.mapCameraKeyframeAnimator(trigger: selectedId) { initialCamera in
let start = initialCamera.centerCoordinate
let end = quakes[selectedId]?.location.coordinate ?? start
let travelDistance = start.distance(to: end)
let duration = max(min(travelDistance / 30, 5), 1)
let finalAltitude = travelDistance > 20 ? 3_000_000 : min(initialCamera.distance, 3_000_000)
let middleAltitude = finalAltitude * max(min(travelDistance / 5, 1.5), 1)
KeyframeTrack(\MapCamera.centerCoordinate) {
CubicKeyframe(end, duration: duration)
}
KeyframeTrack(\MapCamera.distance) {
CubicKeyframe(middleAltitude, duration: duration / 2)
CubicKeyframe(finalAltitude, duration: duration / 2)
}
}
But I don't actually see any map animations taking place when that selection changes.
Running the application from iPhone simulator does show the animations.
I am building from Xcode Version 16.2 and macOS 15.2. Are there known issues with this API on macOS?
Hi! I'm seeing some weird animation issues building the Food Truck sample application.^1 I'm running from macOS 15.4 and Xcode 16.3. I'm building the Food Truck application for macOS. I'm not focusing on iOS for now.
The FoodTruckModel adds new Order values with an animation:
// FoodTruckModel.swift
withAnimation(.spring(response: 0.4, dampingFraction: 1)) {
self.orders.append(orderGenerator.generateOrder(number: orders.count + 1, date: .now, generator: &generator))
}
This then animates the OrdersTable when new Order values are added.
Here is a small change to OrdersTable:
// OrdersTable.swift
- @State private var sortOrder = [KeyPathComparator(\Order.status, order: .reverse)]
+ @State private var sortOrder = [KeyPathComparator(\Order.creationDate, order: .reverse)]
Running the app now inserts new Order values at the top.
The problem is I seem to be seeing some weird animation issues here. It seems that as soon as the new Order comes in there is some kind of weird glitch where it appears as if part the animation is coming from the side instead of down from the top:
What's then more weird is that if I seem to affect the state of the Table in any way then the next Order comes in with perfect animation.
Scrolling the Table fixes the animation.
Changing the creationData sort order from reverse to forward and back to reverse fixes the animation.
Any ideas? Is there something about how the Food Truck product is built that would cause this to happen? Is this an underlying issue in the SwiftUI infra?
https://github.com/apple/sample-food-truck
Hi! I'm seeing what looks like some weird navigation issue in the Food Truck app. It's from the Live Activity that should deep link to a specific point in the app. There seems be some state where the app is not linking to the correct component. Here are my repro steps on iPhone:
Start live activity from OrderDetailView.
Navigate to Sidebar component.
Tap the Live Activity.
App opens TruckView.
The App should be opening the OrderDetailView for the Order that was passed to the Live Activity. This seems to work when the app is not currently on Sidebar.
Any ideas? I'm testing this on iPhone OS 18.4.1. Is this an issue inside NavigationSplitView? Is this an issue with how Food Truck handles deeplinking?