I'm trying to convert some data, then save it back to Core Data. Sometimes this works fine without an issue, but occasionally I'll get an error
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
It seems to occur when saving the core data context. I'm having trouble trying to debug it as it doesn't happen on the same object each time and can't reliably recreate the error
Full view code can be found https://pastebin.com/d974V5Si but main functions below
var body: some View {
VStack {
// Visual code here
}
.onAppear() {
DispatchQueue.global(qos: .background).async {
while (getHowManyProjectsToUpdate() > 0) {
leftToUpdate = getHowManyProjectsToUpdate()
updateLocal()
}
if getHowManyProjectsToUpdate() == 0 {
while (getNumberOfFilesInDocumentsDirectory() > 0) {
deleteImagesFromDocumentsDirectory()
}
if getNumberOfFilesInDocumentsDirectory() == 0 {
DispatchQueue.main.asyncAfter(deadline: .now()) {
withAnimation {
self.isActive = true
}
}
}
}
}
}
}
update local function
func updateLocal() {
autoreleasepool {
let fetchRequest: NSFetchRequest<Project> = Project.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "converted = %d", false)
fetchRequest.fetchLimit = 1
fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Project.name, ascending: true), NSSortDescriptor(keyPath: \Project.name, ascending: true)]
do {
let projects = try viewContext.fetch(fetchRequest)
for project in projects {
currentPicNumber = 0
currentProjectName = project.name ?? "Error loading project"
if let projectMain = project.mainPicture {
currentProjectImage = getUIImage(picture: projectMain)
}
if let pictures = project.pictures {
projectPicNumber = pictures.count
// Get main image
if let projectMain = project.mainPicture {
if let imgThumbData = convertImageThumb(picture: projectMain) {
project.mainPictureData = imgThumbData
}
}
while (getTotalImagesToConvertForProject(project: project ) > 0) {
convertImageBatch(project: project)
}
project.converted = true
saveContext()
viewContext.refreshAllObjects()
}
}
} catch {
print("Fetch Failed")
}
}
}
convertImageBatch function
func convertImageBatch(project: Project) {
autoreleasepool {
let fetchRequestPic: NSFetchRequest<Picture> = Picture.fetchRequest()
let projectPredicate = NSPredicate(format: "project = %@", project)
let dataPredicate = NSPredicate(format: "pictureData == NULL")
fetchRequestPic.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [projectPredicate, dataPredicate])
fetchRequestPic.fetchLimit = 5
fetchRequestPic.sortDescriptors = [NSSortDescriptor(keyPath: \Picture.dateTaken, ascending: true)]
do {
let pictures = try viewContext.fetch(fetchRequestPic)
for picture in pictures {
currentPicNumber = currentPicNumber + 1
if let imgData = convertImage(picture: picture), let imgThumbData = convertImageThumb(picture: picture) {
// Save Converted
picture.pictureData = imgData
picture.pictureThumbnailData = imgThumbData
// Save Image
saveContext()
viewContext.refreshAllObjects()
} else {
viewContext.delete(picture)
saveContext()
viewContext.refreshAllObjects()
}
}
} catch {
print("Fetch Failed")
}
}
}
And finally saving
func saveContext() {
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}