Posts

Post marked as solved
5 Replies
962 Views
How should my code be modified to ensure that when an exception happens at the Core Data layer when adding a new item, that SwiftUI does NOT continue to show a new item? Background: When I run the below code I get an exception when adding a new item doing the "context.save()", HOWEVER whilst the new item request really failed (did not save to Core Data), the UI does show a new item. It is as if the "lists" variable in the @FetchRequest line is not behaving dynamically. Question - How do I fix code so that the application works properly?Code: import SwiftUI struct ContentView: View { @Environment(\.managedObjectContext) var context @FetchRequest(fetchRequest: List.allListFetchRequest()) var lists: FetchedResults private func addListItem() { let newList = List(context: context) newList.id = 1 newList.title = "Testing 123" do { try context.save() } catch let e as NSError { print("Could not save new List. \(e.debugDescription)") return } } var body: some View { NavigationView { VStack { ForEach(lists) { list in Text("List = \(list.title)") } } .navigationBarTitle( Text("My Todo Lists") ) .navigationBarItems( trailing: Button(action: {self.addListItem()} ) { Image(systemName: "plus.square") } ) } } }Example Output: Could not save new List. Error Domain=NSCocoaErrorDomain Code=133021 "(null)" UserInfo={NSExceptionOmitCallstacks=true, conflictList=( "NSConstraintConflict (0x600001fcccc0) for constraint (\n id\n): database: (null), conflictedObjects: (\n \"0x600000a7e360 \",\n \"0xfb1bb528bb57810c \"\n)" )}
Posted
by callagga.
Last updated
.
Post marked as solved
3 Replies
986 Views
How can one prevent auto-zooming with IOS MapKit when using userTrackingMode = .followWithHeading? That is I am setting the current user location to the centre of the screen, and have "view.userTrackingMode = .followWithHeading" so that the map orientates to north, but when you zoom in/out manually the MapView automatically overrides this and zooms back to the level it seems to prefer being at. I was to be able to zoom in, then the zoom level stays like this, whilst it keeps the map centred to user location, and keeps auto-rotating to keep map aligned to north. I am using SwiftUI so have effectively do have the location being passed into GCMapView as a parameter (as the means to keep the SwiftUI GCMapView up to date with latest user location). So not sure if this is causing an issue? Some key bits (have pulled some code out to show relevant lines) of the MapKit call backs I'm using: struct FlightView: View { @EnvironmentObject var locationManager : GCLocationManager @State var centreUserLocation : Bool = false var body: some View { GCMapView( flight: flight, userLocation: locationManager.userLocation, centreUserLocation: centreUserLocation, initalZoomDone: initalZoomDone ) } } struct GCMapView : UIViewRepresentable { let map = MKMapView() func makeUIView(context: Context) -> MKMapView { map.delegate = context.coordinator map.isRotateEnabled = true map.userTrackingMode = .followWithHeading map.showsUserLocation = true return map } func updateUIView(_ view: MKMapView, context: Context) { if let userLocation = userLocation { view.centerCoordinate = userLocation view.userTrackingMode = .followWithHeading // Needed to keep map rotating to align to North } } func makeCoordinator() -> Coordinator { return Coordinator(self) } class Coordinator: NSObject, MKMapViewDelegate { var parent: GCMapView init(_ parent: GCMapView) { self.parent = parent super.init() } } }
Posted
by callagga.
Last updated
.
Post not yet marked as solved
1 Replies
1.4k Views
When moving a row in a SwiftUI List I note that due to my "save Core Data" call the UI transition is jerky. I call save against core data as the list items orderNum has changed, so I'm saving that change that. Video and code below. If I remove the "GCCoreData.save()" there is no stutter.Animated GIF: https://i.stack.imgur.com/lsmtV.gifCode - Extract from my SwiftUI View private var tasksFetchRequest : FetchRequest private var gcTasks : FetchedResults { tasksFetchRequest.wrappedValue } init(withGcList gcList:GCList) { self.currentList = gcList self.tasksFetchRequest = FetchRequest( entity: GCTask.entity(), sortDescriptors: [NSSortDescriptor(key: "orderNum", ascending: true)], predicate: NSPredicate(format: "gcList == %@", currentList) ) } private func updateOrderNums(startIndex: Int, destIndex: Int, inc: Int) { var currIndex = startIndex while currIndex <= destIndex { gcTasks[currIndex].orderNum = gcTasks[currIndex].orderNum + Int64(inc) currIndex += 1 } } fileprivate func moveRow(fromStartIndex taskStartIndex: IndexSet.Element, toDestIndex taskDestIndex: Int, movingDown moveDown: Bool) { gcTasks[taskStartIndex].orderNum = gcTasks[taskDestIndex].orderNum updateOrderNums( startIndex: moveDown ? taskStartIndex + 1 : taskDestIndex, destIndex: moveDown ? taskDestIndex : taskStartIndex - 1, inc: moveDown ? -1 : 1 ) // Save GCCoreData.save() // <<== JERKINESS OCCURS DUE TO THIS }Code - Library functions called class GCCoreData: NSObject { static func save() { let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext if context.hasChanges { do { try context.save() } catch { let nserror = error as NSError fatalError("Unresolved error performing Core Data save: \(nserror), \(nserror.userInfo)") } } } }Note that change the "GCCoreData.save()" line to the below also does not assist. DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) { GCCoreData.save() } [1]: https://i.stack.imgur.com/lsmtV.gif
Posted
by callagga.
Last updated
.
Post not yet marked as solved
0 Replies
380 Views
When using a List which I want to be in edit mode, but do NOT want to use "onDelete" (only want to use "onMove") there is an indentation occuring for the row (a bug I think). See below for example. Any work arounds until this is fixed/addressed?Snapshot Image https://i.stack.imgur.com/UAIIN.png Playground Codeimport SwiftUI import PlaygroundSupport let modelData: [String] = ["Eggs", "Milk", "Bread"] struct ListTestNoDelete: View { private func move(from uiStartIndexSet: IndexSet, to uiDestIndex: Int) { print("On Move") } var body: some View { NavigationView { VStack { List { ForEach(modelData, id: \.self) { str in HStack { Image(systemName: "square") Text(str) } } .onMove(perform: self.move) } .environment(\.editMode, .constant(.active)) .navigationBarTitle( Text("Test") ) } } } } let listTest = ListTestNoDelete() PlaygroundPage.current.liveView = UIHostingController(rootView: listTest)
Posted
by callagga.
Last updated
.
Post not yet marked as solved
0 Replies
691 Views
Is it possible to "re-order"/"move" items in a ScrollView as one can in a List? I have playground below which compiles/run fine, however the onDelete / onMove does does visualise any delete button or hamburger lines for dragging/moving?Is there a way to get my code working here so at least the "onMove" concept works?Note - I note that both List and ScrollView (I think) support protocol DynamicViewContent, so was assuming it should work(?)Image after running code: https://i.stack.imgur.com/c5R8g.pngCode (Playgrounds)import SwiftUI import PlaygroundSupport let modelData: [String] = ["Eggs", "Milk", "Bread"] struct ListTestNoDelete: View { private func move(from uiStartIndexSet: IndexSet, to uiDestIndex: Int) { print("On Move") } private func delete(at offsets : IndexSet) { print("On Delete") } var body: some View { NavigationView { VStack { ScrollView { ForEach(modelData, id: \.self) { str in HStack { Image(systemName: "square") Text(str) Spacer() }.padding(.horizontal, 3) } .onMove(perform: self.move) .onDelete(perform: self.delete) } .environment(\.editMode, .constant(.active)) .navigationBarTitle( Text("Test") ) } } } } let listTest = ListTestNoDelete() PlaygroundPage.current.liveView = UIHostingController(rootView: listTest)
Posted
by callagga.
Last updated
.
Post not yet marked as solved
0 Replies
438 Views
ould the below be the most appropriate way to handle updating the orderNum of items in a List when the manual order is stored in core data (as the orderNum field).Specifically I note when I try to cycle through my fetchedResults list after I have deleted an item, that item is in fact still there. So what I'm doing is doing a core data save, and then after this updating the orderNum and then resaving. OK approach?Key code sections: @Environment(\.managedObjectContext) var context @FetchRequest(fetchRequest: GCList.allListFetchRequest()) var gcLists: FetchedResults private func save() { // Save do { try self.context.save() } catch let e as NSError { print("ERROR : \(e.description)") } } private func deleteList(at offsets: IndexSet) { // Remove Items for index in offsets { let list = self.gcLists[index] self.context.delete(list) } self.save() // Redo orderNum *** NEED TO DO ANOTHER UPDATE/RESAVE LIKE THIS *** var i = 0 self.gcLists.forEach { gcItem in gcItem.orderNum = Int64(i) i += 1 } self.save() }
Posted
by callagga.
Last updated
.
Post not yet marked as solved
1 Replies
1.2k Views
How would remove the delete button in SwiftUI List rows when in Edit Mode? Note the hamburger button on the right of the row that allows rows to be re-ordered needs to continue to function.Background - Want a list that has the "re-order" rows functions always enabled. Edit mode seems to enable this (i.e. leave List in edit mode) however do not want the red delete button on each row.
Posted
by callagga.
Last updated
.