Post

Replies

Boosts

Views

Activity

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
111
2w
Download & replace app container
I used to download and replace the app container when I was testing, essentially downloading the container from the live app, and restoring it into the test app in order to not affect the live app, but to test major changes on "live" data. it seems the option for downloading and replacing in Xcode no longer works, I will sometimes get a container downloaded, other times it only part downloads. I can never seem to get it to replace. No errors, but it doesn't work on the new device. It used to be that devices & simulators showed when it was downloading and replacing but it no longer does that. Is there another way of doing this? Currently I'm having to take a backup of the live phone, restore on the test device, then delete all the unneeded apps, otherwise the restore takes ages, then backup the test device and restore every time I need to restart.
0
1
92
1w
Persist app state across reinstalls/multiple devices
So I’m trying to setup an existing app to work with iCloud syncing. The syncing part seems to be working for the most part. When the app is first installed it sets up some data locally. Throughout the life of the app additional data is added through updates. There is a user default setup that stores the current data version, then compares it with the new version. If it’s newer, then loads the additional data. The issue I’ve got is a user can delete the app and reinstall, or install on another device which has that data version as 0, prompting another import even though the data in the cloud is current version, resulting in duplicate data once the sync is done. How can I persist that version data? I’ve seen NSUbiquitousKeyValueStore which seems to be a cloud based version of user defaults, but it says not to rely on it if it’s critical to app functions
0
0
120
3w
Thumbnails for images saved in core data
I'm trying to look at what the best way to do thumbnails for images that are saved in core data, which are being synced across multiple devices. I know I can save a lower quality version into core data, but I'm wondering if there's a better way of doing it. I've come across quick look thumbnailing which looks like what I want, but I'm not sure if it can be adapted for core data as its using file paths, whereas the images are stored in a data type property in core data. From what I can tell, I'd have to save the image locally, produce the thumbnail, then delete the local image
0
0
137
3w
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<Project> = 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)-> 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 }```
2
0
190
Oct ’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
347
May ’24
Core Data - Create a dynamic filter
I'm trying to setup a filter option for some core data records, but I'm not seeing the expected results. Essentially, what I want is to have multiple sections. Within each section it would be an OR query, and an AND between each section. I've tried setting it up as below. func getBasicFilter() -> NSPredicate? { var predicatesBagsLeft : [NSPredicate] = [] var predicatesDrillType : [NSPredicate] = [] var andPredicates : [NSPredicate] = [] print("Filter List") print(filters) // Bags Left if let show = filters["showFullLeft"] { if show { print("Predicates : Show Full") let predicate = NSPredicate(format: "ANY projectColours.fullLeft > 0") predicatesBagsLeft.append(predicate) } } if let show = filters["showPartialLeft"] { if show { print("Predicates : Show Partial") let predicate = NSPredicate(format: "ANY projectColours.partialLeft > 0") predicatesBagsLeft.append(predicate) } } // Drill Types if let show = filters["showSquareOnly"] { if show { print("Predicates : Show Square Only") let predicate = NSPredicate(format: "ANY projectColours.project.drillType = %@", "Square") predicatesDrillType.append(predicate) } } // Drill Manufacturers - TO DO // Combine Predicates if predicatesBagsLeft.count > 0 { let predicatesForBagsLeft = NSCompoundPredicate(type: .or, subpredicates: predicatesBagsLeft) andPredicates.append(predicatesForBagsLeft) } if predicatesDrillType.count > 0 { let predicatesForDrillType = NSCompoundPredicate(type: .or, subpredicates: predicatesDrillType) andPredicates.append(predicatesForDrillType) } if andPredicates.count > 0 { let predicates = NSCompoundPredicate(type: .and, subpredicates: andPredicates) return predicates } return nil } It does filter, but doesn't seem to be applying both correctly. I'm testing with a filter of showFullLeft & showSquareOnly, so it should show only squares which have a a fullest > 0 I'm getting 7 results back, but one of them is unwanted. It is square, but it has 0 for both full & partial When I look at the query core data is using it looks correct CoreData: sql: SELECT t0.ZMANU, COUNT (DISTINCT t0.Z_PK) FROM ZCOLOUR t0 JOIN ZPROJECTCOLOUR t1 ON t0.Z_PK = t1.ZCOLOUR JOIN ZPROJECTCOLOUR t2 ON t0.Z_PK = t2.ZCOLOUR JOIN ZPROJECT t3 ON t2.ZPROJECT = t3.Z_PK WHERE ( t1.ZFULLLEFT > ? AND t3.ZDRILLTYPE = ?) GROUP BY t0.ZMANU ORDER BY t0.ZMANU CoreData: details: SQLite bind[0] = 0 CoreData: details: SQLite bind[1] = "Square"
0
0
355
Jan ’24
Quick action items - Core Data query & how to navigate
I'm trying to move an app over to swiftui and have run into a couple of issues involving quick actions. I'm trying to get the app to respond to the action. I have a CustomSceneDelegate setup, which is receiving the actions. How do I get it to navigate to a view when the addProject is used, and how do I get a core data query in the addTime? class CustomSceneDelegate: UIResponder, UIWindowSceneDelegate { func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { handleShortcutItem(shortcutItem) } func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) { if shortcutItem.type == "addProject" { print("Phase: Add Project") } else if shortcutItem.type == "addTime" { print("Phase: Add Time") } } }
0
0
250
Jan ’24
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
491
Jan ’24
SwiftData - Assignment randomly failing
I have a SwiftData class which has an attribute of var dimObject : DIM? I'm trying to assign a DIM object to that attribute, buts its randomly failing with Thread 1: EXC_BAD_ACCESS (code=1, address=0x8000000000000010) Its never the same object, nor do I get any further indications of what's causing it. I've narrowed it down to digimon.dimObject = dimFound in the below function func insertDigimon(digimon: Digimon) { Thread.sleep(forTimeInterval: 1) if let dimFound = getDIMFromID(dimID: digimon.dim) { print("****************************************************************") print("Digimon: \(digimon.name) - ID: \(digimon.id)") print("DIM: \(dimFound.name)") print("Set DIM Object on Digimon") digimon.dimObject = dimFound print("Digimon object set") print("Add digimon to DIM") dimFound.addToDigimon(d: digimon) print("Digimon added to DIM") } modelContext.insert(digimon) } If I comment out that line, there's no error Both the digimon and dimFound objects aren't nil and contain the expected object.
0
1
353
Oct ’23
Dynamically changing fetch request
I have the below fetch request which I want to be able to dynamically change the setup of. The request is setup initially as         sectionIdentifier: \.level,         sortDescriptors: [NSSortDescriptor(keyPath: \Card.level, ascending: true),                           NSSortDescriptor(keyPath: \Card.setID, ascending: true),                           NSSortDescriptor(keyPath: \Card.cardID, ascending: true),                           NSSortDescriptor(keyPath: \Card.name, ascending: true)],         animation: .default)     private var cards: SectionedFetchResults<Int16, Card> I've got the predicate change working fine, but get errors with the sort descriptors and the section identifier On setting the sort descriptors I get the error Cannot convert value of type 'NSSortDescriptor' to expected element type 'Array<SortDescriptor>.ArrayLiteralElement' (aka 'SortDescriptor') And setting the section identifier I get Cannot assign value of type 'SectionedFetchResults<String, Card>.Type' to type 'KeyPath<Card, Int16>' The code I have is below.                 if groupBy == 2 {                     cards.nsPredicate = nil                     let sortSetID = NSSortDescriptor(keyPath: \Card.setID, ascending: true)                     let sortName = NSSortDescriptor(keyPath: \Card.name, ascending: true)                     cards.sortDescriptors = [sortSetID, sortName] // This errors                     cards.sectionIdentifier = SectionedFetchResults<String, Card> // This errors                 }
1
0
790
Sep ’22
List with multiple selections from core data
I'm trying to adjust a list so that it can have multiple selection. It works when I use hard coded data, but when I try and use it with core data, the option to edit the list doesn't bring the checkboxes up. Working code struct DIMTest: Identifiable { let id = UUID() let name: String } struct DimTypeListView: View { let contacts = [ DIMTest(name: "John"), DIMTest(name: "Alice"), DIMTest(name: "Bob") ] // 2 @State private var multiSelection = Set<DIM>() var body: some View { NavigationView { VStack { // 3 List(contacts, selection: $multiSelection) { contact in Text(contact.name) } Text("\(multiSelection.count) selections") } .navigationTitle("Contacts") .toolbar { // 4 EditButton() } } } } but when I adjust the code to the below to load from core data, I don't get the checkboxes @SectionedFetchRequest var dims: SectionedFetchResults<Bool, DIM> init(dType: DimType) { _dims = SectionedFetchRequest<Bool, DIM>( sectionIdentifier: \.favourite, sortDescriptors: [NSSortDescriptor(keyPath: \DIM.favourite, ascending: false), NSSortDescriptor(keyPath: \DIM.name, ascending: true)], predicate: NSPredicate(format: "dimType = %@", dType) ) } @State private var multiSelection = Set<DIM>() var body: some View { VStack { List(dims, selection: $multiSelection) { section in Section() { ForEach(section) { dim in Text("Name") } } } Text("\(multiSelection.count) selections") } .navigationTitle("DIMs") .toolbar { EditButton() } } It shows the correct number of entries, but can't be selected If i add an onDelete, i get the delete options but only want to be able to select, not delete
0
0
371
Jun ’23
Collapsible section headers
I have a list with sections headers on two views. One view has the section headers as collapsible, the other doesn't. Both use pretty much the same code, what defines if a section header is collapsible? Code for the one that doesn't collapse ForEach(cards) { section in let header: String = nameForSectionHeader(sectionID: section.id) Section(header: Text(header)) { ForEach(section) { card in NavigationLink(destination: CardView(card: card)) { HStack { Image(card.imageName ?? "") .renderingMode(.original) .resizable() .scaledToFit() .frame(width: 50.0) VStack(alignment: .leading) { if let name = card.name, let id = card.cardID { Text("\(id) - \(name)") } Text("Owned: \(card.owned)") } } } } } } } and the code for the one that does ForEach(cards) { section in let header: String = nameForSectionHeader(sectionID: section.id) Section(header: Text(header)) { ForEach(section) { card in NavigationLink(destination: CardView(card: card)) { VStack(alignment: .leading) { if let name = card.name, let id = card.cardID { Text("\(id) - \(name)") } if let set = card.set, let setName = set.name { Text("Set: \(setName)") } if card.owned > 0 { Text("Owned: \(card.owned)") } } } } } } .listRowBackground(lightGreen) }
1
0
1.2k
Sep ’22
Changing property causes detail view to pop back to list view
I have a list view created from core data, and it's sectioned by a property called favourite. In the detail view a user is able to either add an item or remove it as a favourite. When the property is updated, it causes the detail view to pop back to the list view, which I don't want it to do, and don't know how to get it to not do that The creation of the list @SectionedFetchRequest var dims: SectionedFetchResults<Int16, DIM> init() { _dims = SectionedFetchRequest<Int16, DIM>( sectionIdentifier: \.favourite, sortDescriptors: [NSSortDescriptor(keyPath: \DIM.favourite, ascending: false), NSSortDescriptor(keyPath: \DIM.name, ascending: true)] ) } List { ForEach(dims) { section in let header: String = nameForSectionHeader(sectionID: section.id) Section(header: Text(header)) { ForEach(section) { dim in NavigationLink(destination: DIMListView(dim: dim)) { } } } } } and then on the detail view there's a toolbar with an option to add/remove favourite. .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Options") { showingAlertFav = true } .alert("Choose an option", isPresented: $showingAlertFav) { if dim.favourite == 0 { Button("Favourite", role: .none) { setFav(fav: 1) } } else { Button("Unfavourite", role: .none) { setFav(fav: 0) } } } } } func setFav(fav : Int16) { dim.favourite = fav saveContext() }
0
0
349
May ’23
Xcode git keeps complaining of unsaved changes
Xcode keeps complaining about changes when I try and commit, I get the error "The local repository is out of date." When I try and pul changes from the remote, I get the message "Your local repository has uncommitted changes that need to be stashed before you can continue. " When I try and commit, every time it shows a UserInterfaceState.xcuserstate file. if I try and commit it I get the local repository error.
1
0
1.1k
Apr ’23