SwiftData property marked ephemeral getting persisted in CloudKit

Am I misunderstanding the expected behavior here, or is there a bug in the behavior of @Attribute(.ephemeral) tagged SwiftData model properties?

The documentation for .ephemeral says "Track changes to this property but do not persist". I started using .ephemeral because @Transient was inhibiting SwiftUI from reacting to changes to the property through @Observable.

I am updating the value of my @Attribute(.ephemeral) property about once a second and I am seeing corresponding console log output showing the property as part of the generated CKRecord object. I then confirmed in the CloudKit dev portal that the .ephemeral property was added to the Record schema and contains real values. The behavior seems as though the .ephemeral property is being completely ignored.

This is observed in a new Xcode project using SwiftData with CloudKit, Xcode 16.2, macOS 15.3.1 and during Build & Run testing on physical devices.

What you described seems to be a bug on the framework side. To confirm that, would you mind to check if the .ephemeral attribute exists in the SwiftData store on your device? You can do so with the following steps:

a. Find your SwiftData store folder by running the following code in your app

if let configuration = modelContext.container.configurations.first {
    print("StoreURL = \(configuration.url)")
}

b. Run sqlite3 command line in your Mac system:

$ cd <Your SwiftData store folder>
$ ls
default.store		default.store-shm	default.store-wal
$ sqlite3 ./default.store
...
sqlite> .tables
...
// Find the table named "Z<your SwiftData model type name>"
sqlite> .schema <the table name>
CREATE TABLE ... ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ... );

c. In the CREATE TABLE line, check if there is something name "Z<your ephemeral attribute name>".

I tried with my iOS 18.2 simulator and didn't see my SwiftData .ephemeral attribute is persisted, which is expected. I am wondering if you see the same thing on your side though.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

I've observed this too (iOS 18.7.2 and 26.2). Looks like @Attribute(.ephemeral) does nothing and the property is annotated with @_PersistedProperty as any other property and SwiftData.Schema.Attribute(.ephemeral) metadata has no effect.

I think it only happens for Codable properties.

In the following example, b is not persisted, but c is.

struct C: Codable {
    var value: Int
}

@Model
class Item {
    var a = 0
    @Attribute(.ephemeral) var b = 0
    @Attribute(.ephemeral) var c = C(value: 0)
    init() { }
}

struct ContentView: View {
    
    @Query var items: [Item]
    @Environment(\.modelContext) var modelContext
    
    var body: some View {
        List {
            Section {
                Button("add") {
                    modelContext.insert(Item())
                }
            }
            Section {
                ForEach(items) { item in
                    VStack(alignment: .leading) {
                        HStack {
                            Text("a = \(item.a)")
                            Button("inc") {
                                item.a += 1
                            }
                        }
                        HStack {
                            Text("b = \(item.b)")
                            Button("inc") {
                                item.b += 1
                            }
                        }
                        HStack {
                            Text(verbatim: "c = \(item.c)")
                            Button("inc") {
                                item.c.value += 1
                            }
                        }
                    }
                    .buttonStyle(.borderedProminent)
                }
            }
        }
    }
}

There's also a behavior that seems stranger. Whenever the app goes to background, b is reset to zero.

SwiftData property marked ephemeral getting persisted in CloudKit
 
 
Q