Когда я извлекаю сущности после пакетной вставки в контекст управляемого объекта основной очереди для обновления списка SwiftUI, я замечаю, что всегда есть дубликаты (точнее, буквальное удвоение каждой сущности).
Я выполняю пакетную вставку файлов, которые пользователь импортирует, с помощью метода «импорт файлов» в классе Manager. Затем я извлекаю их в контекст управляемого объекта основной очереди, чтобы обновить свой список SwiftUI.
class DataController {
static let shared = DataController()
func createNewBackgroundContext() -> NSManagedObjectContext {
let taskContext = container.newBackgroundContext()
taskContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
return taskContext
}
}
class Manager {
func importFiles(from urls: [URL]) async {
let importContext = DataController.shared.createNewBackgroundContext()
var objects: [[String: Any]] = []
for url in urls {
if url.startAccessingSecurityScopedResource() {
let metadata = getMetadata(url: url)
let audioFileName = url.deletingPathExtension().lastPathComponent
let fileExtension = url.pathExtension
let artist = metadata?.value(forKey: "artist") as? String ?? "Unknown Artist"
let album = metadata?.value(forKey: "album") as? String ?? "Unknown Album"
let genre = metadata?.value(forKey: "genre") as? String ?? "Unknown Genre"
let composer = metadata?.value(forKey: "composer") as? String ?? "Unknown Composer"
let year = metadata?.value(forKey: "year") as? String ?? "Unknown Release Year"
let importDate = Date()
let artwork = audioFileName + ".\(fileExtension)"
let trackNumber = metadata?.value(forKey: "trackNumber") as? Int ?? -1
let properties: [String: Any] = [
"name": audioFileName,
"artist": artist,
"album": album,
"genre": genre,
"year": year,
"composer": composer,
"importDate": importDate,
"trackNumber": trackNumber,
"artwork": artwork,
"fileExtension": fileExtension,
"favourite": false
]
objects.append(properties)
//Save the file to disk
save(url: url, with: audioFileName + ".\(fileExtension)")
}
url.stopAccessingSecurityScopedResource()
}
//objects array is confirmed to have the right number of items to be inserted
await importContext.perform { [weak self] in
guard let self else { return }
let batchInsertRequest = NSBatchInsertRequest(entity: AudioFile.entity(), objects: objects)
batchInsertRequest.resultType = .objectIDs
let result = try? importContext.execute(batchInsertRequest) as? NSBatchInsertResult
let objs = result?.result as? [NSManagedObjectID] ?? []
//The number of ids is always double here for some reason...
let changes: [AnyHashable: Any] = [NSInsertedObjectIDsKey: objs]
// Merge changes
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes, into: [moc])
}
await MainActor.run {
SongsListViewModel.shared.fetchAudioFiles()
}
}
}
class SongsListViewModel: ObservableObject {
static let shared = AllSongsListViewModel()
@Published var audioFiles = [AudioFile]()
private let moc = DataController.shared.container.viewContext
func fetchAudioFiles() {
let fetchRequest = AudioFile.fetchRequest()
if let audioFiles = try? moc.fetch(fetchRequest) {
self.audioFiles = audioFiles
}
}
}
Дубликаты файлов не записывались. Также не было создано дубликатов объектов для вставки в пакетный запрос. Я предполагаю, что это из-за проблем с контекстом нескольких объектов, поскольку существует как основной, так и частный контекст?
Кроме того, дубликаты возникают только после того, как я немедленно извлекаю аудиофайлы. Когда я закрываю приложение и загружаю аудиофайлы, дубликатов нет.





Я нашел источник повторяющихся записей. Если кто-нибудь захочет объяснить, почему для параметра «shouldMigrateStoreAutomatically» должно быть установлено значение true, чтобы предотвратить вставку NSBatchInsertRequest копии для каждого объекта, это было бы здорово.
let description = NSPersistentStoreDescription()
//I have set this property of the description to false all along. Apparently this must be set to true to avoid duplicates when performing a NSBatchInsertRequest
//description.shouldMigrateStoreAutomatically = false
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions = [description]
Не было никакой информации об этом при переполнении стека или каких-либо упоминаний об этом в документации Apple.
Какие действия по устранению неполадок вы здесь выполнили: у вас есть повторяющиеся записи, но проверили ли вы, есть ли у вас повторяющиеся файлы, добавили ли вы какие-либо операторы печати в свой код, чтобы следить за ходом выполнения и т. д... Воспроизвести это практически невозможно для кто-нибудь еще, поэтому нам нужна вся имеющаяся у вас информация.