The selected items are from a SwiftUI list view. User taps on a row to add a song.
The user can add about 10k to 100k songs to a playlist and I want to perform a batch insert request only once the user confirms by pressing “Done” in batches.
The issue is how do I deal with storing the large array of user selected songs? If the user presses cancel, the array will be discarded.
I am also not sure if it is a good idea to batch insert a single song every time they select a song to be added to a playlist and then batch delete if they were to cancel creating the playlist.
I’m using the NSBatchInsertRequest initialiser that takes in an array of dictionary objects. I’m noticing heavy memory usage when attempting to create 100k objects in the dictionary and then calling the execute method to execute the batch request.
class PlaylistManager {
var objects: [[String: Any]] = []
func addSongsToPlaylist(with id: UUID) {
for i in 0...100000 {
let properties: [String: Any] = [
"name": "Song (i)",
"artist": "Some Artist",
"fileExtension": "mp3",
"playlistId": id
]
objects.append(properties)
}
}
func saveSongs() async {
let context = DataController.shared.createNewBackgroundContext()
let mainContext = DataController.shared.container.viewContext
await context.perform { [weak self] in
guard let self else { return }
let batchInsertRequest = NSBatchInsertRequest(entity: Song.entity(), objects: objects)
batchInsertRequest.resultType = .objectIDs
let result = try? context.execute(batchInsertRequest) as? NSBatchInsertResult
let objectIDs = result?.result as? [NSManagedObjectID] ?? []
let changes: [AnyHashable: Any] = [NSInsertedObjectIDsKey: objectIDs]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [mainContext])
}
}
}
4