Track model changes with SwiftData history - WWDC24

Peter Yaacoub •


Introduction

These are some notes I took while watching the WWDC24 session: Track Model Changes with SwiftData History.

Besides SwiftData’s new features involving efficiency and customization, its new history feature provides great ways for syncing offline changes, discovering out-of-process changes, and reloading data efficiently. Starting with iOS 18 and all equivalent Apple platforms, you won’t be limited to querying only from the data store’s most recent state.

How it Works

The SwiftData history is composed of transactions, conforming to HistoryTransaction, that group changes, conforming to HistoryChange, which can be HistoryDelete, HistoryInsert, or HistoryUpdate. All transactions and changes are sorted by the time of occurrence.

When using the default data store, all the mentioned protocols use their default counterparts, which are the protocols to which they conform.

Preserving Values

To preserve values in the history, or the “tombstone” as Apple calls it, you add the Attribute macro with the preserveValueOnDeletion Option to the concerned model’s properties.

For instance, I would add this attribute option in my app, Huh? Dictionary, if I believed that I’d need to preserve my SearchEntry’s word property.

import Foundation
import SwiftData

@Model
final class SearchEntry {
    
    // MARK: - Init
    
    init(word: String) {
        self.word = word
    }
    
    // MARK: - Properties
    
    @Attribute(.unique, .preserveValueOnDeletion) var word: String
    var date: Date = Date.now

}

Note also that you can delete the history for a certain model at any time if you deem the information not useful anymore.

Fetching from History

Fetching information from the history consists of finding the transactions and processing the transactions.

In the first step, you use a HistoryDescriptor, while in the second, you use a FetchDescriptor for each transaction change to match the persistentModelId with the changedPersistentIdentifier.

Conclusion

If I could go back in time and have an influence on the new SwiftData changes, I wouldn’t change anything because I wouldn’t be qualified and because I find the history to be a very welcome improvement in democratizing Apple’s one-year-old framework.