Hello,
I am quite new to iOS programming and I am currently implementing my first iOS app with SwiftUI and CoreData. I have a question and I hope you can help me.
My app has multiple tabs and my Core Data persistence objects can be fetched, manipulated and deleted from different Views and Tabs.
I have a Detail-View that is used for multiple pages accessible from Tab 1 and Tab 2.
So, it may be the case that a user opens the Detail-View on Tab 1, then switches to the same Detail-View on Tab 2.
If now the user deletes the persistence object used for the Detail-View on one of the Tabs, I want that the Detail-View gets hidden and want to transition back to the previous List-View.
However, If I switch to my other Tab, my Detail-View now still shows my Detail-View, but without any data (I checked if my attribute is nil).
I think it may be appropriate if the Detail-View will also disappear and switch to the parent List-View for the other Tab, if the persistence object does not exists anymore.
I found that I can check a persistence objects isFault attribute, which is true, after I deleted and saved my changes via the NSManagedObjectContext.var body: some View {
		List {
if self.myPersistenceObject.isFault {
// persistence Object was deleted
Text(LocalizedStringKey("Persistence enity has fault"))
} else {
// persistence Object is alive
RealDetailView()
...
This works in a way, that I see a Text, if my persistence object is not available anymore and otherwise shows the real Detail-View.
But thats not quite that what I want…
I tried to check if if my persistence object isFault also .onAppear and set my Bool @Binding variable to false, if my persistence object is not available anymore.struct DetailView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@ObservedObject var myPersistenceObject: MyPersistenceObject
@Binding var presentView: Bool
...
.onAppear {
if myPersistenceObject.isFault {
self.presentView = false
}
}
struct ListViewTab1: View {
@ObservedObject var myPersistenceObject: MyPersistenceObject
@State var presentDetailView: Bool = false
var body: some View {
NavigationLink(
destination:
DetailView(myPersistenceObject: myPersistenceObject,
presentView: $presentDetailView),
isActive: $presentDetailView,
label: {
Text("Label")
}
)
}
}
The presentView Binding is passed from my List-View into my Detail-View.
However, dismissing my view with this Bool-Binding only works for one of my Tabs and not for the other one. That is, if I delete the object from the Detail-View in Tab 1 the Detail-View gets dismissed on deletion, but if I switch to the other Tab, the Detail-View has not been dismissed.
Has anybody also struggled with issues where SwiftUI views were not updated correctly after a CoreData persistence object was deleted?
My project has grown quite big already, so I have not yet a more complete example ready. However, maybe anybody also had that issue and solved it differently.
If not, I will work on a small reproducible example in the next weeks.
Anyway, thank you for reading my question and for any support.
Best,
Bernhard
Post
Replies
Boosts
Views
Activity
I use Xcode 12.2 and iOS build target 14.1.
I have the problem with my SwiftUI app that closing views that use NavigationLink one after the other does not work.
The problem occurs with the following Swift source code when I first navigate to View4, click on "Dismiss" and then click on "Dismiss" again on View3. The latter button click causes no action. To get the "Dismiss" button of View3 working again, I would have to go to View2 with the Back button and then switch back to View3.
I tried previously to use "presentationMode.wrappedValue.dismiss()", however that did not work with fewer views.
minimal reproducible Example:
struct View1: View {
		@State var presentView2: Bool = false
		
		var body: some View {
				NavigationView {
						List {
								NavigationLink(
										destination: View2(types: ["Exams"], presentView2: $presentView2),
										isActive: $presentView2,
										label: {
												Text("View2")
										})
						}.listStyle(InsetGroupedListStyle())
						.navigationTitle("View1")
				}
		}
}
struct View2: View {
		var types: [String]
		@State var presentView3: Bool = false
		@Binding var presentView2: Bool
		
		var body: some View {
				List {
						Section {
								NavigationLink("View3", destination: View3(presentView3: $presentView3), isActive: $presentView3)
						}
						
						Section {
								Button(action: {self.presentView2 = false}, label: {
										Text("Dismiss")
								})
						}
				}
				.listStyle(InsetGroupedListStyle())
				.navigationTitle(LocalizedStringKey("View2"))
		}
}
struct View3: View {
		@Binding var presentView3: Bool
		@State var presentView4: Bool = false
		@State
		var isAddViewPresented: Bool = false
		var body: some View {
				List {
						Section {
								NavigationLink("View4", destination: View4(presentView4: $presentView4), isActive: $presentView4)
						}
						
						Button(action: {presentView3 = false}, label: {
								Text("Dismiss")
						})
				}
				.listStyle(InsetGroupedListStyle())
				.navigationTitle("View3")
				.toolbar {
						ToolbarItem {
								Button(action: {isAddViewPresented.toggle()}, label: {
										Label("Add", systemImage: "plus.circle.fill")
								})
						}
				}
				.sheet(isPresented: $isAddViewPresented, content: {
						Text("DestinationDummyView")
				})
		}
}
struct View4: View {
		@Binding var presentView4: Bool
		
		var body: some View {
				List {
						Button(action: {presentView4 = false}, label: {
								Text("Dismiss")
						})
				}
				.listStyle(InsetGroupedListStyle())
				.navigationTitle("View4")
		}
}
does anybody have a solution for that?
Specifically, I need this in my application to delete records from the app (first the child, then the parent).
thank you for any feedback and input! ☺️☺️☺️