Post

Replies

Boosts

Views

Activity

Saving images to core data runs of memory
I'm trying to do a mass conversion of images to data so it can be stored in core data. The conversion part works fine, and if I do it without updating core data it shows memory usage at less that 100MB If I update the core data object, it just keeps consuming memory until the app crashes. func updateLocalImages() { let fetchRequest: NSFetchRequest<Picture> = Picture.fetchRequest() fetchRequest.predicate = NSPredicate(format: "pictureName != \"\"") do { let pictures = try moc.fetch(fetchRequest) print("Picture Update Count: \(pictures.count)") for picture in pictures { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let path = paths[0] if let picName = picture.pictureName { let imagePath = path.appendingPathComponent(picName) if let uiImage = UIImage(contentsOfFile: imagePath.path) { if let imageData = uiImage.jpegData(compressionQuality: 1.0) { autoreleasepool { picture.pictureData = imageData print("Picture Updated") saveContext() } } } } } } catch { print("Fetching Failed") } } If I comment out the picture.pictureData = imageData line I don't get the memory issues. What's the correct way of going about this? There is an unknown number of images (mine current sits at about 5.5GB worth, 800+)
1
0
639
Jan ’24
Setting up Query in init causes app to freeze
I'm trying to filter results to get all characters that are associated with a story. When navigating to the view it filters as it should, but as soon as you select the Add Character option, the app just freezes. I've found that if I comment out the Query line in the init, and filter out as part of the foreach I don't get the freeze. Can anyone advise how I should be doing these predicates as it seems init isn't the best place to do it The views code is import SwiftUI import SwiftData struct CharacterListView: View { let story : Story @Query(sort: \Character.name, order: .forward) private var characters: [Character] var body: some View { List { ForEach(characters) { char in CharacterListCellView(char: char) } } .toolbar { ToolbarItem { NavigationLink(destination: CharacterAddView(story: story)) { Label("Add Character", systemImage: "plus") } } } .navigationBarTitle("Characters", displayMode: .inline) } init(story: Story) { self.story = story let id = story.persistentModelID let predicate = #Predicate<Character> { char in char.story?.persistentModelID == id } _characters = Query(filter: predicate, sort: [SortDescriptor(\.name)] ) } } I've narrowed it down to a line in the AddCharacterView file struct CharacterAddView: View { @Environment(\.modelContext) private var modelContext @Environment(\.dismiss) var dismiss let story : Story // Character details @State private var characterName: String = "" // Images @State private var showImageMenu = false; @State private var isShowPhotoLibrary = false @State private var isShowCamera = false //@State private var image = UIImage() <-- This line @State private var imageChanged = false @State private var isSaving : Bool = false var body: some View { } } If I do either of the below it works If I comment out the UIImage variable then I don't get the freeze, but I can't update the image variable If I comment out the query in init, then it works but doesn't filter and I have to do it as part of the foreach
1
1
570
May ’24
Filtered list when going back from pushed view
I have the below code for my view's body Currently when I go to the ItemDetailView View and then press back to return to this view, the filtered list is no longer there, it's back the full view. How to I get it to keep the filtered list when I go back? The text is still in the search bar         NavigationLink(destination: ItemAddView(series: series), isActive: $noItemsShowing) { EmptyView() }         List {             ForEach(items) { item in                 NavigationLink(destination: ItemDetailView(item: item)) {                     Text(fullItemName(item: item))                 }             }         }         .searchable(text: $searchText)         .onSubmit(of: .search) {             items.nsPredicate = NSPredicate(format: "series = %@", series)             if(!searchText.isEmpty) {                 items.nsPredicate = NSPredicate(format: "series = %@ AND amount > 0 AND name CONTAINS[cd] %@", series, searchText)             }         }         .onChange(of: searchText) { _ in             items.nsPredicate = NSPredicate(format: "series = %@", series)             if(!searchText.isEmpty) {                 items.nsPredicate = NSPredicate(format: "series = %@ AND amount > 0 AND name CONTAINS[cd] %@", series, searchText)             }         }         .navigationBarTitle("\(series.name ?? "Error") Items", displayMode: .inline)     }
2
0
631
May ’22
Updating from Navigation view to NavigationStack
I'm currently using a navigationview and am now getting an warning 'init(destination:tag:selection:label:)' was deprecated in iOS 16.0: use NavigationLink(value:label:) inside a List within a NavigationStack or NavigationSplitView I'm trying to move to another view from a button (there will be several hence using tags) but I can't seem to get my head around how to do it. The code I currently have var body: some View { List { NavigationLink(destination: ProjectColourAddView(project: project), tag: 1, selection: $action) { EmptyView() } Group { Button(action: { self.showImageMenu = true }) { Text("New Title Image") } .confirmationDialog("Select Image Source", isPresented: $showImageMenu, titleVisibility: .visible) { Button("Take Photo") { self.isShowCamera = true } Button("Choose from Albums") { self.isShowPhotoLibrary = true } } Button(action: { self.action = 3 NSLog("More Images") }) { Text("More Images (x)") } Button(action: { self.action = 2 NSLog("Add Image") }) { Text("Add Image") } Button(action: { self.action = 1 NSLog("Colour List") }) { Text("Colour List") } } } }
2
0
664
Apr ’23
List Cell - Modifying associated object causes reload of whole list
I've got a List containing Colour objects. Each colour may have an associated Project Colour object. What I'm trying to do is set it up so that you can tap a cell and it will add/remove a project colour. The adding/removing is working, but each time I do so, it appears the whole view is reloaded, the scroll position is reset and any predicate is removed. This code I have so far List { ForEach(colourList) { section in let header : String = section.id Section(header: Text(header)) { ForEach(section) { colour in HStack { if checkIfProjectColour(colour: colour) { Image(systemName: "checkmark") } VStack(alignment: .leading){ HStack { if let name = colour.name { Text(name) } } } Spacer() } .contentShape(Rectangle()) .onTapGesture { if checkIfProjectColour(colour: colour) { removeProjectColour(colour: colour) } else { addProjectColour(colour: colour) } } } } } .onAppear() { filters = appSetting.filters colourList.nsPredicate = getFilterPredicate() print("predicate: on appear - \(String(describing: getFilterPredicate()))") } .refreshable { viewContext.refreshAllObjects() } } .searchable(text: $searchText) .onSubmit(of: .search) { colourList.nsPredicate = getFilterPredicate() } .onChange(of: searchText) { colourList.nsPredicate = getFilterPredicate() } The checkIfProjectColour function func checkIfProjectColour(colour : Colour) -> Bool { if let proCols = project.projectColours { for proCol in proCols { let proCol = proCol as! ProjectColour if let col = proCol.colour { if col == colour { return true } } } } return false } and the add/remove functions func addProjectColour(colour : Colour) { let projectColour = ProjectColour(context: viewContext) projectColour.project = project projectColour.colour = colour colour.addToProjectColours(projectColour) project.addToProjectColours(projectColour) do { try viewContext.save() } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } func removeProjectColour(colour: Colour) { if let proCols = project.projectColours { for proCol in proCols { let proCol = proCol as! ProjectColour if let col = proCol.colour { if col == colour { viewContext.delete(proCol) do { try viewContext.save() } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } } } } } }
2
0
266
Nov ’24
Cloud Kit - Synching image
I'm currently sharing data between devices using core data and cloud kit.Currently I have a "Picture" entity which stores the filename, the date it was added and a relation to another entity.The details in core data successfully syncs, how would I go about syncing the image file. The file is saved in the documents folder and I can get its file path usinglet imagePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(imageName)Research seems to show I need to use CKAsset to upload/download the file but how do I go about doing this?
3
0
2.2k
May ’21
UIImage causes memory to run out
I have a project that currently has data saved locally and I'm trying to get it to sync over multiple devices. Currently basic data is syncing perfectly fine, but I'm having issues getting the images to convert to data. From what I've researched it because I'm using a UIImage to convert and this caches the image It works fine when there's only a few images, but if there's several its a pain The associated code func updateLocalImages() { autoreleasepool { let fetchRequest: NSFetchRequest&lt;Project&gt; = Project.fetchRequest() fetchRequest.predicate = NSPredicate(format: "converted = %d", false) fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Project.statusOrder?.sortOrder, 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 pictures = project.pictures { projectPicNumber = pictures.count for pic in pictures { currentPicNumber = currentPicNumber + 1 let picture : Picture = pic as! Picture if let imgData = convertImage(picture: picture) { picture.pictureData = imgData } } project.converted = true saveContext() } } } catch { print("Fetch Failed") } } } func convertImage(picture : Picture)-&gt; Data? { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let path = paths[0] if let picName = picture.pictureName { let imagePath = path.appendingPathComponent(picName) if let uiImage = UIImage(contentsOfFile: imagePath.path) { if let imageData = uiImage.jpegData(compressionQuality: 0.5) { return imageData } } } return nil }```
3
0
1k
Jan ’25
EXC_BAD_ACCESS When saving core data
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)") } }
6
0
202
Jul ’25