Skip to main content

How to store SwiftData attributes in an external file

About 2 minSwiftArticle(s)bloghackingwithswift.comcrashcourseswiftswiftdataxcodeappstore

How to store SwiftData attributes in an external file ꎀ렚

SwiftData by Example

Back to Home

How to store SwiftData attributes in an external file | SwiftData by Example

How to store SwiftData attributes in an external file

Updated for Xcode 15

SwiftData is great for storing information such as strings, integers, dates, and custom Codable objects, but if you’re storing larger data such as images or even movies it’s a good idea to have SwiftData store them in external, peripheral files, then reference those filenames in your SwiftData object.

Helpfully, SwiftData makes this trivial using the .externalStorage attribute, which suggests to SwiftData that this data is best stored separately. It will, if needed, stash that data externally from your main SwiftData storage, store only the filename to the external data, then transparently connect the two so you don’t need to take any further action – for the most part external data behaves no differently from internal data.

For example, if you were storing a game player’s avatar, you might have code like this:

@Model class User {
    var name: String
    var score: Int
    @Attribute(.externalStorage) var avatar: Data

    init(name: String, score: Int, avatar: Data) {
        self.name = name
        self.score = score
        self.avatar = avatar
    }
}

You can combine this with other attributes, such as encryption, like this:

@Attribute(.externalStorage, .allowsCloudEncryption) var avatar: Data

There are three important provisos when dealing with external storage, and it’s important that you’re aware of them.

First, the .externalStorage attributes merely suggests to SwiftData that some information is best stored outside the main SQLite data store, but it doesn’t have to honor that request. In my tests with this attribute, SwiftData seems happy to store up to about 128K of a Data object right inside its main storage area, with larger data automatically being saved externally.

Second, if you’re using String rather than Data, SwiftData seems happy to store strings of unlimited size without using external files at all no matter whether you use the attribute or not.

Third, for the most part all this is an implementation detail: whether the data is stored right inside the database or not doesn’t matter to us, because it’s loaded and saved the same as internal data. However, you can’t use externally stored properties inside predicates, because the external files aren’t visible to the underlying data store – if you see an error message like [Foundation.__NSSwiftData _bytesPtrForStore]: unrecognized selector sent to instance 0x600000c74ae0 with userInfo of (null) chances are you might have fallen into this trap.


ìŽì°ŹíŹ (MarkiiimarK)
Never Stop Learning.