Skip to content

Instantly share code, notes, and snippets.

@philipshen
Last active June 8, 2024 04:12
Show Gist options
  • Save philipshen/9e265d471beecb82adba8e6b3a61fc4b to your computer and use it in GitHub Desktop.
Save philipshen/9e265d471beecb82adba8e6b3a61fc4b to your computer and use it in GitHub Desktop.
func replaceCachedContacts(_ contacts: [UserOrContact]) throws {
let modelContext = ModelContext(modelContainer)
let internalIdSet = Set(contacts.map { $0.internalId })
var internalIdsToNotInsert = Set<String>()
var existingInternalIdsToDelete = Set<String>()
let existingContacts = try modelContext.fetch(
FetchDescriptor<UserOrContact>(
predicate: #Predicate { internalIdSet.contains($0.internalId) }
)
)
let internalIdsToExistingContacts = existingContacts
.reduce(into: [String: UserOrContact]()) {
$0[$1.internalId] = $1
}
for contact in contacts {
if contact.equalProperties(to: internalIdsToExistingContacts[contact.internalId]) {
internalIdsToNotInsert.insert(contact.internalId)
} else {
existingInternalIdsToDelete.insert(contact.internalId)
}
}
try modelContext.transaction {
// Delete models which have changed or – if deleteOthers is true – do not exist in
// the models parameter
try modelContext.delete(model: UserOrContact.self, where: #Predicate {
existingInternalIdsToDelete.contains($0.internalId) || !internalIdSet.contains($0.internalId)
})
// Insert new and changed models
for contact in contacts {
guard !internalIdsToNotInsert.contains(contact.internalId) else {
continue
}
modelContext.insert(contact)
}
}
}
@philipshen
Copy link
Author

Hey Robert! First off, really appreciate you taking the time to provide some feedback. It's all very helpful and I've incorporated all of it into my project.

It's an excellent point to avoid instantiating PersistentModel instances for objects that will (very likely) be discarded; using a struct instead should improve the performance here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment