// ######################################################################################## // XCode // Version 11.5.1 (11E503a) // Simulator // Version 11.4.1 (921.9) // SimulatorKit 581.9.1 // CoreSimulator 704.12.1 // Device // iPhone SE (2nd generation) (Works as expected) // iPad (7th generation) (Has the issue) // ######################################################################################## // ######################################################################################## // You will need to create CoreDataentities as follows: // // Entity: SomeEntity // @NSManaged public var date: Date? (Attribute) // Entity: Location // @NSManaged public var name: String? (Attribute) // ######################################################################################## //################################################################################ // the issue I am having is with the ipad only and when it is using .navigationViewStyle(DoubleColumnNavigationViewStyle()) // this is the default style when in landscape mode but I am also forcing it in portrait // // the iphone works as expected because it is not using DoubleColumnNavigationViewStyle() at all // if i force StackNavigationViewStyle on the iPad, the problem is not present but the user experience suffers greatly // // I have now two different issues // Issue 1) The same begavior as descibed in my previous demo where Multiple form1s get injected in the navigation Path // Issue 2) The date Picker closes automatically when the user changes one part of the date // // compared to my previous Demo, in this Demo: // 1) I select a date using a datePicker instead of a coredata record using a Picker // 2) I never save the CoreData // 3) since a save never occurs, I removed the NotificationCenter for NSManagedObjectContextDidSave // // This demo contains 4 lists. Two works perfectly, the other two have different issues // // List 1 in Stack mode and List1 in DobleColumn mode // In this case, the coredata and Date binding variables are creted in the list1 and passed along the navigation // In the DoubleColumn version, this causes both issues when changing de CoreData DatePicker // // List 2 in Stack mode and List1 in DobleColumn mode // In this case, only the coredata is creted in the list2 and passed along the navigation // the State var is created localy in formB // In the DoubleColumn version, this causes only the issue where the DatePicker closes prematurely when changing de CoreData DatePicker // // I have commented the code where I found that it had effect on the issue // As far as I know there is nothing in there that is rocket science // Unless I missed something, this might be a bug with the DoubleColumnNavigationViewStyle // Everything works fine when it is no used but I would prefer to be able to use it //################################################################################ import SwiftUI import CoreData extension SomeEntity { public var wrappedDate: Date{ get{date ?? Date() } set{date = newValue } } } struct ContentView: View { @State private var selection = 0 @Environment(\.managedObjectContext) var moc var body: some View { TabView(selection: $selection){ Button(action: { self.addOneSomeEntityRecord() }) { Text("Add CoreData Record") } .font(.title) .tabItem { VStack { Image(systemName: "gear") Text("Setup") } } .tag(0) List1().navigationViewStyle(StackNavigationViewStyle()) .font(.title) .tabItem { VStack { Image(systemName: "square") Text("Stack(1)") } } .tag(1) List1().navigationViewStyle(DoubleColumnNavigationViewStyle()).padding(.leading, 0.5) .font(.title) .tabItem { VStack { Image(systemName: "square.split.2x1") Text("DoubleColumn(1)") } } .tag(2) List2().navigationViewStyle(StackNavigationViewStyle()) .font(.title) .tabItem { VStack { Image(systemName: "square") Text("Stack(A)") } } .tag(3) List2().navigationViewStyle(DoubleColumnNavigationViewStyle()).padding(.leading, 0.5) .font(.title) .tabItem { VStack { Image(systemName: "square.split.2x1") Text("DoubleColumn(A)") } } .tag(4) } } func addOneSomeEntityRecord() { let t1 = SomeEntity(context: moc) t1.date = Date() do { try moc.save() } catch { fatalError("Unable to save data") } } } struct List1: View { @FetchRequest(entity: SomeEntity.entity(), sortDescriptors:[], predicate: nil) var entities: FetchedResults<SomeEntity> @State var someDate: Date = Date() var body: some View { NavigationView{ List() { ForEach(entities, id: \.self) { someEntity in List1Row(someEntity:someEntity, someDate : self.$someDate) } } .navigationBarTitle(Text("List1"), displayMode: .inline) } } } struct List1Row: View { @ObservedObject var someEntity:SomeEntity @Binding var someDate: Date var body: some View { HStack { Text("To Form 1") NavigationLink("", destination: Form1(someEntity: someEntity, someDate : $someDate)) } } } struct Form1: View { @ObservedObject var someEntity:SomeEntity @Binding var someDate: Date //################################################################################ // removing this also removes the issue even if it is not currently used in the code // in my real application i need to show a list of locations so i will need a fetch @FetchRequest(entity: Location.entity(), sortDescriptors:[], predicate: nil) var locations: FetchedResults<Location> //################################################################################ var body: some View { Form{ Section(header: Text("Locations")) { ForEach(1...3, id: \.self) { _ in Form1Row(someEntity:self.someEntity, someDate : self.$someDate) } } } .navigationBarTitle("Form1") } } struct Form1Row: View { @ObservedObject var someEntity:SomeEntity @Binding var someDate: Date var body: some View { NavigationLink("To Form 2", destination: Form2(someEntity: someEntity, someDate : $someDate)) } } struct Form2: View { @ObservedObject var someEntity:SomeEntity @Binding var someDate: Date private var coreDataSomeDateSaver:Binding<Date> { Binding<Date>(get: {self.someEntity.wrappedDate }, set: { self.someEntity.date = $0 //################################################################################ // Even if I don't save here, the problem still occurs // in the final application, I plan to save here // let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext // do { try moc.save() } catch {} //################################################################################ }) } var body: some View { Form{ //################################################################################ // only the date picker binded to a coredata record that has been passed along from the list has the issue // if it would have been defined in form1 it would not have the issue //################################################################################ DatePicker("CoreDate :", selection: coreDataSomeDateSaver, displayedComponents: .date) //################################################################################ // I would expect the behavior to be the same as DatePicker where the selection is on a Binding // The binding DatePicker workds regardless of where the binding variable was first defined // but it has impact on the DatePicker that handles a coredata record // in this case, the binding was defined in list1 and passed along to here. // this causes the multiple Form1 bug occurs and the selection view is closed prematurely as soon as a value changed //################################################################################ DatePicker("Binding :", selection: $someDate, displayedComponents: .date) } .navigationBarTitle("Form2") } } struct List2: View { @FetchRequest(entity: SomeEntity.entity(), sortDescriptors:[], predicate: nil) var entities: FetchedResults<SomeEntity> var body: some View { NavigationView{ List() { ForEach(entities, id: \.self) { someEntity in List2Row(someEntity:someEntity) } } .navigationBarTitle(Text("List1"), displayMode: .inline) } } } struct List2Row: View { @ObservedObject var someEntity:SomeEntity var body: some View { HStack { Text("To Form A") NavigationLink("", destination: FormA(someEntity: someEntity)) } } } struct FormA: View { @ObservedObject var someEntity:SomeEntity //################################################################################ // removing this also removes the issue even if it is not currently used in the code // in my real application i need to show a list of locations so i will need a fetch @FetchRequest(entity: Location.entity(), sortDescriptors:[], predicate: nil) var locations: FetchedResults<Location> //################################################################################ var body: some View { Form{ Section(header: Text("Locations")) { ForEach(1...3, id: \.self) { _ in FormARow(someEntity:self.someEntity) } } } .navigationBarTitle("FormA") } } struct FormARow: View { @ObservedObject var someEntity:SomeEntity var body: some View { NavigationLink("To Form B", destination: FormB(someEntity: someEntity)) } } struct FormB: View { @ObservedObject var someEntity:SomeEntity @State var someDate: Date = Date() private var coreDataSomeDateSaver:Binding<Date> { Binding<Date>(get: {self.someEntity.wrappedDate }, set: { self.someEntity.date = $0 //################################################################################ // Even if I don't save here, the problem still occurs // in the final application, I plan to save here // let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext // do { try moc.save() } catch {} //################################################################################ }) } var body: some View { Form{ //################################################################################ // only the date picker binded to a coredata record that has been passed along from the list has the issue // if it would have been defined in formA it would not have the issue //################################################################################ DatePicker("CoreDate :", selection: coreDataSomeDateSaver, displayedComponents: .date) //################################################################################ // I would expect the behavior to be the same as DatePicker where the selection is on a State variable // Defining a State variable locally for the DatePicker works // but it has impact on the DatePicker that handles a coredata record // In this case, the Multiple form1 issue does not happend // but the selection view is closed prematurely as soon as a value changed //################################################################################ DatePicker("State :", selection: $someDate, displayedComponents: .date) } .navigationBarTitle("FormB") } }