ios – SwiftData Model not updating values provided in init


I’m attempting to maintain a local copy of server data in my application and thought I could accomplish this with (in fact, I’ve followed this article about it in the official Apple Documentation). However, SwiftData ignores the values set in the @Model initializer and any subsequent attempts to update the values.

My impression was that: by using the @Attribute(.unique) value on the id parameter, any time I created a model with the same ID as an existing one, SwiftData would update the existing model. That doesn’t appear to be the case.

I can’t quite determine why SwiftData is not allowing me to update my model (esp. from inside the model’s own initializer). Is this a bug? Some undocumented behavior? Or have I just got things configured incorrectly, or am using these models in an unsupported way?


This behavior can be replicated using a simple model object and initializer like this:

@Model
final class Item {
    
    @Attribute(.unique)
    var id: String
    
    var timestamp: Date
    
    var deleted: Bool
    
    // Initializes a local SwiftData model from a "RemoteItem", which is just a Codable
    // object generated from a server response.
    //
    init?(from remoteModel: RemoteItem) {
        guard let remoteId = remoteModel.id else { return nil }
        self.id = remoteId
        self.timestamp = remoteModel.timestamp
        
        print("Initialized Item model with deletion value from remote model: \(remoteModel.deleted)")
        // Prints correct value of deleted to the console (e.g. true)

        self.deleted = remoteModel.deleted
        
        print("Initialized Item model with remote deletion. Value is now: \(self.deleted)")
        // Prints INCORRECT value of deleted to the console (e.g. false)
    }
    
}

Then, in a data source actor (or other similar class):

func fetchItems() async throws -> [Item] {
    let someRemoteItems = try await networkRequestForRemoteItems()
        
    // Map the remote items to locally cached items, similar to the demo
    // provided by Apple here: https://developer.apple.com/documentation/swiftdata/maintaining-a-local-copy-of-server-data
    let localItemCopies: [Item] = someRemoteItems.compactMap({ Item(from: $0) })
    
    // "Cache" the remote items
    for localItem in localItemCopies {
        await cacheContainer.insert(localItem)
    }

    return localItemCopies
}

As noted above, any items that already existed locally in the SwiftData model store are not updated when inserted again here. And for additional context, I’ve seen other questions asking about similar behavior but only in the context of SwiftUI, which is not relevant here.

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img