I have encountered an issue that when using a ModelActor to sync data in the background, the app will crash if one of the operations is to remove a PersistentModel from the context.
This is running on the latest beta of Xcode 16 with visionOS 1.2 as target and in Swift 6 language mode.
The code is being executed in a ModelActor.
The error is first thrown by:
#5 0x00000001c3223280 in PersistentModel.getValue<τ_0_0>(forKey:) ()
Thread 1: Fatal error: Context is missing for Optional(SwiftData.PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://97AA86BC-475D-4509-9004-D1182ABA1922/Reminder/p303), implementation: SwiftData.PersistentIdentifierImplementation))
func globalSync() async {
await fetchAndSyncFolders()
let result = await fetchReminders()
switch result {
case .success(let ekReminders):
var localReminders = (try? await fetch(FetchDescriptor<Reminder>())) ?? []
// Handle local reminders with nil ekReminderID by creating new EKReminders for them
for reminder in localReminders {
if reminder.ekReminderID == nil {
await self.createEkReminder(reminder: reminder)
}
}
// Re-fetch local reminders to include newly created EKReminderIDs
localReminders = (try? await fetch(FetchDescriptor<Reminder>())) ?? []
var localReminderDict = [String: Reminder]()
for reminder in localReminders {
if let ekReminderID = reminder.ekReminderID {
if let existingReminder = localReminderDict[ekReminderID] {
self.delete(model: existingReminder)
} else {
localReminderDict[ekReminderID] = reminder
}
}
}
let ekReminderDict = createReminderLookup(byID: ekReminders)
await self.syncReminders(localReminders: Array(localReminderDict.values), localReminderDict: localReminderDict, ekReminderDict: ekReminderDict)
// Merge duplicates
await self.mergeDuplicates(localReminders: localReminders)
save()
case .failure(let error):
print("Failed to fetch reminders: \(error.localizedDescription)")
}
}
Post
Replies
Boosts
Views
Activity
Hi team,
I'm running into the following issue, for which I don't seem to find a good solution.
I would like to be able to drag and drop items from a view into empty space to open a new window that displays detailed information about this item.
Now, I know something similar has been flagged already in this post (FB13545880: Support drag and drop to create a new window on visionOS)
HOWEVER, all this does, is launch the App again with the SAME WindowGroup and display ContentView in a different state (show a selected product e.g.).
What I would like to do, is instead launch ONLY the new WindowGroup, without a new instance of ContentView.
This is the closest I got so far. It opens the desired window, but in addition it also displays the ContentView WindowGroup
WindowGroup {
ContentView()
.onContinueUserActivity(Activity.openWindow, perform: handleOpenDetail)
}
WindowGroup(id: "Detail View", for: Reminder.ID.self) { $reminderId in
ReminderDetailView(reminderId: reminderId! )
}
.onDrag({
let userActivity = NSUserActivity(activityType: Activity.openWindow)
let localizedString = NSLocalizedString("DroppedReminterTitle", comment: "Activity title with reminder name")
userActivity.title = String(format: localizedString, reminder.title)
userActivity.targetContentIdentifier = "\(reminder.id)"
try? userActivity.setTypedPayload(reminder.id)
// When setting the identifier
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(reminder.persistentModelID),
let jsonString = String(data: jsonData, encoding: .utf8) {
userActivity.userInfo = ["id": jsonString]
}
return NSItemProvider(object: userActivity)
})
func handleOpenDetail(_ userActivity: NSUserActivity) {
guard let idString = userActivity.userInfo?["id"] as? String else {
print("Invalid or missing identifier in user activity")
return
}
if let jsonData = idString.data(using: .utf8) {
do {
let decoder = JSONDecoder()
let persistentID = try decoder.decode(PersistentIdentifier.self, from: jsonData)
openWindow(id: "Detail View", value: persistentID)
} catch {
print("Failed to decode PersistentIdentifier: \(error)")
}
} else {
print("Failed to convert string to data")
}
}