Here we have yet another bug, I suppose, in SwiftData that happens on iOS18 but it is not an issue on iOS17.
There are 2 models defined as follows
@Model
final public class Note: Identifiable, Codable, Hashable
{
public private(set) var uuid = UUID().uuidString
var heading: String = ""
var tags: [Tag]?
init(heading: String = "") {
self.heading = heading
}
required public init(from decoder: Decoder) throws {
...
}
public func encode(to encoder: Encoder) throws {
...
}
}
@Model
final public class Tag: Identifiable, Codable
{
var name: String = ""
@Relationship(deleteRule: .nullify, inverse: \Note.tags) var notes: [Note]?
init(_ name: String) {
self.name = name
}
required public init(from decoder: Decoder) throws {
…
}
public func encode(to encoder: Encoder) throws {
...
}
}
and a function o add new tags as follows
private func addTags(note: Note, tagNames: [String]) {
if note.tags == nil {
note.tags = []
}
for tagName in tagNames {
if let tag = fetchTag(tagName) {
if !note.tags!.contains(where: {$0.name == tagName}) {
note.tags!.append(tag)
}
} else {
// The following line throws the exception on iOS18 when Tag conforms to Codable:
// Illegal attempt to map a relationship containing temporary objects to its identifiers.
note.tags!.append(Tag(tagName))
}
}
}
This code works perfectly well on iOS17 but on iOS18 I get the exception “Illegal attempt to map a relationship containing temporary objects to its identifiers.”
What I noticed that this happens only when Tag model conforms to Codable protocol. Is it a bug? It looks like, otherwise we've got some undocumented changes have been made.
In my previous post I mentioned about the other issue about ModelContext that is broken too on iOS18 - I mean it works perfectly well on iOS17.
Demo app with an example how to workaround this problem is available here on GitHub.
Repro steps:
Add a note with some tags (separated by space)
Edit this note and add a new tag (tag that does not exists in database) and tap Save.
You should noticed that the tag hasn't been added. It works occasionally but hardly to be seen.
iCloud & Data
RSS for tagLearn how to integrate your app with iCloud and data frameworks for effective data storage
Post
Replies
Boosts
Views
Activity
Use CloudKit's ckqueryoperation's recordmatchedblock in Swift 6.0, which always crashes, but works fine in Swift 5:
func fetchAllRecords() async throws {
let predicate = NSPredicate(format: "Topics = %@", "Integrations")
let query = CKQuery(recordType: "PureMList", predicate: predicate)
let operation = CKQueryOperation(query: query)
operation.recordMatchedBlock = { recordID, result in
switch result {
case .success(let record):
DispatchQueue.main.async {
// Ensure UI updates happen here
print("Fetched record: \(record)")
// Update your UI elements here
}
case .failure(let error):
// Handle the error
print("Error fetching record with ID \(recordID): \(error)")
}
}
// Ensure you're using the correct database
publicDatabase.add(operation)
}
I'm seeing these errors in the console when calling ModelContainer(for:migrationPlan:configurations) for iOS 18:
error: Attempting to retrieve an NSManagedObjectModel version checksum while the model is still editable. This may result in an unstable verison checksum. Add model to NSPersistentStoreCoordinator and try again.
CoreData: error: Attempting to retrieve an NSManagedObjectModel version checksum while the model is still editable. This may result in an unstable verison checksum. Add model to NSPersistentStoreCoordinator and try again.
Is this anything to be concerned about?
(Side note: "version" is misspelled in "verison checksum")
Core Data not returning results in ShieldConfiguration Extension, but works fine in other extensions
Hi everyone,
I’m using Core Data in several extensions (DeviceActivityMonitor, ShieldAction, and ShieldConfiguration). It works perfectly in DeviceActivityMonitor and ShieldAction. I’m able to successfully fetch data and log the correct count using a fetch request.
However, when I try the same setup in the ShieldConfiguration extension, the fetch request always returns 0 results. The CoreData and App Group setup appears to be correct since the first two extensions fetch the expected data.
I’ve also previously tested storing the CoreData objects separately in a JSON-FIle using FileManager and it worked without issues—though I’d prefer not to handle manual encoding/decoding if possible.
The documentation mentions that the extension runs in a sandbox, restricting network requests or moving sensitive content. But shouldn’t reading data (from a shared App Group, for instance) still be possible within the sandbox, as it is the case with the Files, what is the difference there? In my case, I only need to read the data, as modifications can be handled via ShieldActionExtension.
Any help would be greatly appreciated!
is anyone facing the error, "The current model reference and the next model reference cannot be equal", when using SwiftData with migration and iCloud/CloudKit integration?
Hello,
SwiftData is not working correctly with Swift Concurrency. And it’s sad after all this time.
I personally found a regression. The attached code works perfectly fine on iOS 17.5 but doesn’t work correctly on iOS 18 or iOS 18.1.
A model can be updated from the background (Task, Task.detached or ModelActor) and refreshes the UI, but as soon as the same item is updated from the View (fetched via a Query), the next background updates are not reflected anymore in the UI, the UI is not refreshed, the updates are not merged into the main.
How to reproduce:
Launch the app
Tap the plus button in the navigation bar to create a new item
Tap on the “Update from Task”, “Update from Detached Task”, “Update from ModelActor” many times
Notice the time is updated
Tap on the “Update from View” (once or many times)
Notice the time is updated
Tap again on “Update from Task”, “Update from Detached Task”, “Update from ModelActor” many times
Notice that the time is not update anymore
Am I doing something wrong? Or is this a bug in iOS 18/18.1?
Many other posts talk about issues where updates from background thread are not merged into the main thread. I don’t know if they all are related but it would be nice to have
1/ bug fixed, meaning that if I update an item from a background, it’s reflected in the UI, and
2/ proper documentation on how to use SwiftData with Swift Concurrency (ModelActor). I don’t know if what I’m doing in my buttons is correct or not.
Thanks,
Axel
import SwiftData
import SwiftUI
@main
struct FB_SwiftData_BackgroundApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(for: Item.self)
}
}
}
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@State private var simpleModelActor: SimpleModelActor!
@Query private var items: [Item]
var body: some View {
NavigationView {
VStack {
if let firstItem: Item = items.first {
Text(firstItem.timestamp, format: Date.FormatStyle(date: .omitted, time: .standard))
.font(.largeTitle)
.fontWeight(.heavy)
Button("Update from Task") {
let modelContainer: ModelContainer = modelContext.container
let itemID: Item.ID = firstItem.persistentModelID
Task {
let context: ModelContext = ModelContext(modelContainer)
guard let itemInContext: Item = context.model(for: itemID) as? Item else { return }
itemInContext.timestamp = Date.now.addingTimeInterval(.random(in: 0...2000))
try context.save()
}
}
.buttonStyle(.bordered)
Button("Update from Detached Task") {
let container: ModelContainer = modelContext.container
let itemID: Item.ID = firstItem.persistentModelID
Task.detached {
let context: ModelContext = ModelContext(container)
guard let itemInContext: Item = context.model(for: itemID) as? Item else { return }
itemInContext.timestamp = Date.now.addingTimeInterval(.random(in: 0...2000))
try context.save()
}
}
.buttonStyle(.bordered)
Button("Update from ModelActor") {
let container: ModelContainer = modelContext.container
let persistentModelID: Item.ID = firstItem.persistentModelID
Task.detached {
let actor: SimpleModelActor = SimpleModelActor(modelContainer: container)
await actor.updateItem(identifier: persistentModelID)
}
}
.buttonStyle(.bordered)
Button("Update from ModelActor in State") {
let container: ModelContainer = modelContext.container
let persistentModelID: Item.ID = firstItem.persistentModelID
Task.detached {
let actor: SimpleModelActor = SimpleModelActor(modelContainer: container)
await MainActor.run {
simpleModelActor = actor
}
await actor.updateItem(identifier: persistentModelID)
}
}
.buttonStyle(.bordered)
Divider()
.padding(.vertical)
Button("Update from View") {
firstItem.timestamp = Date.now.addingTimeInterval(.random(in: 0...2000))
}
.buttonStyle(.bordered)
} else {
ContentUnavailableView(
"No Data",
systemImage: "slash.circle", //
description: Text("Tap the plus button in the toolbar")
)
}
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}
}
}
private func addItem() {
modelContext.insert(Item(timestamp: Date.now))
try? modelContext.save()
}
}
@ModelActor
final actor SimpleModelActor {
var context: String = ""
func updateItem(identifier: Item.ID) {
guard let item = self[identifier, as: Item.self] else {
return
}
item.timestamp = Date.now.addingTimeInterval(.random(in: 0...2000))
try! modelContext.save()
}
}
@Model
final class Item: Identifiable {
var timestamp: Date
init(timestamp: Date) {
self.timestamp = timestamp
}
}
My app is able to receive data updates when it is in foreground.
however, when i move it in background then sync engine stops syncing until I again move app to foreground.
I'm trying to get the CoreDataCloudKitShare example to work, but having trouble. The first error I see when running the InitializeCloudKitSchema target (on macOS) is the following:
error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(1242): <NSCloudKitMirroringDelegate: 0x60000229c0f0>: Failed to set up CloudKit integration for store: <NSSQLCore: 0x15b807830> (URL: file:///Users/rmann/Library/Application%20Support/InitializeCloudKitSchema/CoreDataStores/Private/private.sqlite)
<CKError 0x600001311290: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 3E1B1380-AE1C-4B14-97A8-7F60B4A8F3EF; container ID = "iCloud.com.example.CoreDataCloudKitShareH6F2W964VK"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x60000132f810: "Permission Failure" (10/2007); server message = "Invalid bundle ID for container"; op = F3987848B25CEED7; uuid = 3E1B1380-AE1C-4B14-97A8-7F60B4A8F3EF>
}>
I see a database in the Dashboard with that container ID, but don't know what it means by "Invalid bundle ID for container". I've seen several other posts about this across the web, and the only answer is ever "seems to be an Apple issue, wait a bit."
Hello everyone,
I’ve recently encountered an issue where my app is working perfectly fine, but I’m seeing an “OTHER” error in the CloudKit dashboard under errors. I’ve checked the logs and there doesn’t seem to be any obvious failure or issue affecting the app’s functionality.
The error doesn’t provide much detail, and I’m having trouble identifying the root cause since everything appears to be functioning as expected in the app. Has anyone else experienced this? Is this something that could be related to a server-side issue, or am I missing something on my end?
Any insights or advice would be greatly appreciated!
Thanks in advance!
The WWDC2024 custom data store example doesn't provide any details on how one would go about creating a DataStoreSnapshot. The example uses a DefaultSnapshot for persisting the data in the DefaultSnapshot format directly in the JSON file.
There appears to be no documentation or examples of how one might create a DataStoreSnapshot from data from another database.
The Apple documentation for DefaultSnapshot provides no examples of how one might create such a snapshot from data retrieved elsewhere.
Can anyone provide a simple example of how one might create such a snapshot from a remote database such that it can be returned as part of the response to a fetch request.
For the purpose of this example let's assume I have a CSV file with rows of data and code to read the data from this file. How would I create a snapshot or snapshots for each of the rows of data.
Hello,
I have a problem with SwiftData and Predicates that check for the persistentModelID of the relations.
My data model looks simplified like this:
Day -> TimeEntry[] -> Hashtag[]
What I want to achieve is to query the days and associated time entries via assigned tags.
This is my predicate:
let identifier = filterHashtags.map(\.persistentModelID)
...
#Predicate<TimeEntry> { timeEntry in
identifiers.count == timeEntry.tags.filter { tag in
identifiers.contains(tag.persistentModelID)
}.count
}
It does not return any data when I check for the persistentModelID. However, if I use another property of the tags, e.g. the name or a generated UUID for the check, the predicate works. Is this a general problem with PersistentIdentifier in Predicates or am I missing something?
Thanks in advance
Hello,
I'm trying to understand how dangerous it is to read and/or update model properties from a thread different than the one that instantiated the model.
I know this is wrong when using Core Data and we should always use perform/performAndWait before manipulating an object but I haven't found any information about that for SwiftData.
Question: is it safe to pass an object from one thread (like MainActor) to another thread (in a detached Task for example) and manipulate it, or should we re fetch the object using its persistentModelID as soon as we cross threads?
When running the example app below with the -com.apple.CoreData.ConcurrencyDebug 1 argument passed at launch enabled, I don't get any Console warning when I tap on the "Update directly" button. I'm sure it would trigger a warning if I were using Core Data.
Thanks in advance for explaining.
Axel
--
@main
struct SwiftDataPlaygroundApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(for: Item.self)
}
}
}
struct ContentView: View {
@Environment(\.modelContext) private var context
@Query private var items: [Item]
var body: some View {
VStack {
Button("Add") {
context.insert(Item(timestamp: Date.now))
}
if let firstItem = items.first {
Button("Update directly") {
Task.detached {
// Not the main thread, but firstItem is from the main thread
// No warning in Xcode
firstItem.timestamp = Date.now
}
}
Button("Update using persistentModelID") {
let container: ModelContainer = context.container
let itemIdentifier: Item.ID = firstItem.persistentModelID
Task.detached {
let backgroundContext: ModelContext = ModelContext(container)
guard let itemInBackgroundThread: Item = backgroundContext.model(for: itemIdentifier) as? Item else { return }
// Item on a background thread
itemInBackgroundThread.timestamp = Date.now
try? backgroundContext.save()
}
}
}
}
}
}
@Model
final class Item: Identifiable {
var timestamp: Date
init(timestamp: Date) {
self.timestamp = timestamp
}
}
I'm trying to write a SwiftUI iOS/macOS app that allows users to collaborate, but I keep running into limitations. The latest is that I can't figure out what the UICloudSharingContainer equivalent is on macOS. It doesn't seem like there’s a SwiftUI version of this, so I have to write a lot of platform-specific code to handle it, but it's not clear what the AppKit equivalent is.
I have a working ValueTransformer that runs fine in simulator/device, but crashes in SwiftUI Preview. Even though they are the same code.
Here is my code
import Foundation
final class StringBoolDictTransformer: ValueTransformer {
override func transformedValue(_ value: Any?) -> Any? {
guard let stringBoolDict = value as? [String: Bool] else { return nil }
let nsDict = NSMutableDictionary()
for (key, bool) in stringBoolDict {
nsDict[key] = NSNumber(value: bool)
}
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: nsDict, requiringSecureCoding: true)
return data
} catch {
debugPrint("Unable to convert [Date: Bool] to a persistable form: \(error.localizedDescription)")
return nil
}
}
override func reverseTransformedValue(_ value: Any?) -> Any? {
guard let data = value as? Data else { return nil }
do {
guard let nsDict = try NSKeyedUnarchiver.unarchivedDictionary(ofKeyClass: NSString.self, objectClass: NSNumber.self, from: data) else {
return nil
}
var result = [String: Bool]()
for (key, value) in nsDict {
result[key as String] = value.boolValue
}
return result
} catch {
debugPrint("Unable to convert persisted Data to [Date: Bool]: \(error.localizedDescription)")
return nil
}
}
override class func allowsReverseTransformation() -> Bool {
true
}
override class func transformedValueClass() -> AnyClass {
NSDictionary.self
}
}
and here is the container
public struct SwiftDataManager {
public static let shared = SwiftDataManager()
public var sharedModelContainer: ModelContainer
init() {
ValueTransformer.setValueTransformer(
StringBoolDictTransformer(), forName: NSValueTransformerName("StringBoolDictTransformer")
)
let schema = Schema([,
Plan.self
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
sharedModelContainer = try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}
}
and the model
@Model
final class Plan {
@Attribute(.transformable(by: StringBoolDictTransformer.self))
var dict: [String: Bool] = [:]
}
I would get that container and pass it in appdelegate and it works fine. I would get that container and pass it inside a #Preview and it would crash with the following:
Runtime: iOS 17.5 (21F79) - DeviceType: iPhone 15 Pro
CoreFoundation:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "dict"; desired type = NSDictionary; given type = _NSInlineData; value = {length = 2, bytes = 0x7b7d}.'
libsystem_c.dylib:
abort() called
Version 16.0 (16A242d)
Hi,
I did cloudkit synchronization using swiftdata.
However, synchronization does not occur automatically, and synchronization occurs intermittently only when the device is closed and opened.
For confirmation, after changing the data in Device 1 (saving), when the data is fetched from Device 2, there is no change.
I've heard that there's still an issue with swiftdata sync and Apple is currently troubleshooting it, is the phenomenon I'm experiencing in the current version normal?
I am trying to get my head around SwiftData, and specifically some more "advanced" ideas that I have not seen covered in the various tutorials.
Specifically, I have a class that includes a collection that may or may not contain elements. For now I am experimenting with a simple array of Date, and I don't know if I should make it an optional, or an empty array. Without SwiftData in the mix it seems like it's probably programmers choice, but I wonder if SwiftData handles those two scenarios differently, that would suggest one over the other.
Recently I've been working on a demo project called iLibrary. The main goal was to learn more about CloudKit and SwiftData. After a while I noticed that there were some hangs/freezes when running the app in debug mode.
I first tried this with Xcode 15.4 and iOS 17.5. Here the hang only appears at the beginning, but only for a few seconds. But when I exit debug mode, there are no more hangs.
With Xcode 16 beta 4 and iOS 18 it looks completely different. In this case, the hangs and freezes are always present, whether in debug mode or not. And it's not just at the beginning, it's throughout the app. I'm aware that this is still a beta, but I still find this weird. And when I profile this I see that the main thread gets quite overloaded. Interestingly, my app doesn't have that many operations going on. So I guess something with the sync of SwiftData or my CloudKitManger where I fetch some records from the public database is not running fine.
Lastly, I wanted to delete the iCloud app data. So I went to Settings and tried to delete it, but it didn't work. Is this normal?
Does anyone have any idea what this could be? Or has anyone encountered this problem as well? I'd appreciate any support.
My project: https://github.com/romanindermuehle/iLibrary
First off, given that I didn't find a tag for Code Review, I hope I am not out of scope for the forums here.
Second, some background. I am a long time Windows Power Shell developer, moving to Swift because I don't like self loathing. :)
Currently I am trying to get my head around SwiftData, and experimenting with creating a Service to handle the actual SwiftData functionality, and a Manager to handle various tasks that relate to instances of the Model. I am doing this realizing that it MAY NOT be the best approach, but it gives me reps both producing code and thinking about how to solve a problem, which I think is useful even if the actual product in throw away. That said, I am hoping someone with more experience than I can comment on this approach, especially with respect to expanding to more models, more complex models, lots of data and a desire to use ModelActor eventually.
DataManagerApp.swift
import SwiftData
import SwiftUI
@main
struct DataManagerApp: App {
let container: ModelContainer
init() {
let schema = Schema([DataModel.self])
let config = ModelConfiguration("SwiftDataStore", schema: schema)
do {
let modelContainer = try ModelContainer(for: schema, configurations: config)
DataService.instance.assignContainer(modelContainer)
container = modelContainer
} catch {
fatalError("Could not configure SwiftData ModelContainer.")
}
}
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(container)
}
}
}
DataModel.swift
import Foundation
import SwiftData
@Model
final class DataModel {
var date: Date
init(date: Date) {
self.date = date
}
}
final class DataService {
static let instance = DataService()
private var modelContainer: ModelContainer?
private var modelContext: ModelContext?
private init() {}
func assignContainer(_ container: ModelContainer) {
if modelContainer == nil {
modelContainer = container
modelContext = ModelContext(modelContainer!)
} else {
print("Attempted to assign ModelContainer more than once.")
}
}
func addModel(_ dataModel: DataModel) {
modelContext?.insert(dataModel)
}
func removeModel(_ dataModel: DataModel) {
modelContext?.delete(dataModel)
}
}
final class ModelManager {
static let instance = ModelManager()
let dataService: DataService = DataService.instance
private init() {}
func newModel() {
let newModel = DataModel(date: Date.now)
DataService.instance.addModel(newModel)
}
}
ContentView.swift
import SwiftData
import SwiftUI
struct ContentView: View {
@Environment(\.modelContext) var modelContext
@State private var sortOrder = SortDescriptor(\DataModel.date)
@Query(sort: [SortDescriptor(\DataModel.date)]) var models: [DataModel]
var body: some View {
VStack {
addButton
List {
ForEach(models) { model in
modelRow(model)
}
}
.listStyle(.plain)
}
.padding()
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
addButton
}
}
}
}
private extension ContentView {
var addButton: some View {
Button("+ Add") {
ModelManager.instance.newModel()
}
}
func modelRow(_ model: DataModel) -> some View {
HStack {
Text(model.date.formatted(date: .numeric, time: .shortened))
Spacer()
}
}
}
Hi,
when using CKSynEgine it is the responsibility of the app to implement CKSyncEngineDelegate. One of the methods of CKSyncEngineDelegate is nextFetchChangesOptions. The implementation of this method should return a batch of CKRecords so that CKSyncEngine can do the syncing whenever it thinks it should sync. A simple implementation might look like this:
func nextRecordZoneChangeBatch(
_ context: CKSyncEngine.SendChangesContext,
syncEngine: CKSyncEngine) async -> CKSyncEngine.RecordZoneChangeBatch?{
await CKSyncEngine.RecordZoneChangeBatch(pendingChanges: syncEngine.state.pendingRecordZoneChanges) { recordID in
// here we should fetch to local representation of the value and map it to a CKRecord
}
}
The problem I am having is as follows:
If the CKRecords I am returning in a batch have dependencies between each other (using CKRecord.Reference or the parent property) but are not part of the same batch, the operation could fail. And as far as I understand, there is no way to prevent this situation because:
A:
The batch I can return is limited in size. If the number of CKRecords is too large, I have to split them into multiple batches.
B:
Splitting them is arbitrary, since I only have the recordID at this point, and there is no way to know about the dependencies between them just by looking at the recordID.
So basically my question is: how should the implementation of nextRecordZoneChangeBatch look like to handle dependencies between CKRecords?
I've been struggling to get a ValueTransformer to work while developing in Xcode 16 for iOS 18. Despite thinking I had everything set up correctly, I keep encountering the following error whenever I create a tag:
let tag = Tag(name: name, color: color.toPlatformColor()) // Converts it to NSColor or UIColor
modelContext.insert(tag)
SwiftData/DataUtilities.swift:184: Fatal error: Unable to determine the primitive for Attribute - name: color, options: [transformable with Optional("ColorTransformer")], valueType: UIColor, defaultValue: UIExtendedSRGBColorSpace 0 0 1 1, hashModifier: nil
Here’s what I’m dealing with:
Tag Model:
@Model
public final class Tag: Identifiable {
var name: String = ""
@Attribute(.transformable(by: ColorTransformer.self))
var color: PlatformColor = PlatformColor.blue
init(name: String, color: PlatformColor) {
self.name = name
self.color = color
}
}
ColorTransformer:
final class ColorTransformer: ValueTransformer {
override func transformedValue(_ value: Any?) -> Any? {
guard let color = value as? PlatformColor else { return nil }
do {
let data = try NSKeyedArchiver.archivedData(
withRootObject: color, requiringSecureCoding: true)
return data
} catch {
assertionFailure("Failed to transform `PlatformColor` to `Data`")
return nil
}
}
override func reverseTransformedValue(_ value: Any?) -> Any? {
guard let data = value as? NSData else { return PlatformColor.black }
do {
let color = try NSKeyedUnarchiver.unarchivedObject(
ofClass: PlatformColor.self, from: data as Data)
return color
} catch {
assertionFailure("Failed to transform `Data` to `PlatformColor`")
return nil
}
}
override class func transformedValueClass() -> AnyClass {
return PlatformColor.self
}
override class func allowsReverseTransformation() -> Bool {
return true
}
public static func register() {
ValueTransformer.setValueTransformer(ColorTransformer(), forName: .colorTransformer)
}
}
extension NSValueTransformerName {
static let colorTransformer = NSValueTransformerName(rawValue: "ColorTransformer")
}
Platform Alias:
#if os(macOS)
typealias PlatformColor = NSColor
#else
typealias PlatformColor = UIColor
#endif
The ValueTransformer is registered when the ModelContainer is created at app startup:
var sharedModelContainer: ModelContainer = {
ColorTransformer.register()
// Other configurations...
}()
I've also tried not aliasing the colors to see if that changes anything, but I still encounter the same issue. Any guidance or suggestions would be greatly appreciated!