Just wanted to clarify something on my post above.
After running some tests and reading @DTS Engineer’s post again, I realized .externalStorage isn't related to whether an attribute is exported to CloudKit as an asset. This behavior also isn’t limited to the Data type.
NSPersistentCloudKitContainer can convert variable-length attributes (Data, String, Transformable) into a CKAsset when exported to CloudKit. We don’t have direct control over when this occurs, but the documentation describes automatic conversion as needed to fit within CloudKit’s 1 MB record-size limit. Otherwise, Binary Data and Transformable values can be stored inline as BYTES, while Strings can remain String fields.
So I can see why @DTS Engineer’s suggestion of adding a configuration option would help here.
I submitted FB25290802, including a small sample project comparing three cases.
300 KB stored in a SwiftData Data attribute, exported as inline Bytes: 2.9 MB reported iCloud usage ❌.
300 KB uploaded directly as a CKAsset, leaving SwiftData empty: 300.4 KB reported iCloud usage ✅.
1 MB stored in a SwiftData Data attribute, automatically exported as an asset: 1 MB reported iCloud usage ✅.
In this test, storing approximately 1 MB through SwiftData used less reported iCloud storage than storing 300 KB through the same attribute, which is completely unexpected.
The feedback requests one or both of these changes:
Add explicit asset-storage control to SwiftData and NSPersistentCloudKitContainer. Allow developers to request CKAsset storage for an attribute, or configure the automatic conversion threshold, while retaining managed synchronization.
Reduce the storage cost of inline Bytes, or prefer assets where they materially reduce user quota usage. If inline storage provides necessary performance benefits, document those tradeoffs and let developers choose.
I understand there may be technical reasons for the different representations, but the additional user storage cost is significant.
Topic:
App & System Services
SubTopic:
iCloud
Tags: