0

I am trying to get a my contentview to update correctly when I change a property in a child view. The view displays all the data correctly, but does not update until you back up a level in the UI and go back to the child view. The child view that does not update is embedded in NavigationView -> List -> Section -> NavigationLink -> List -> ForEach -> NavigationLink.

The same child view updates content view correctly when embedded in NavigationView -> List -> Section -> ForEach -> NavigationLink.

userManager is an instance of a class containing my data, added to the environment

user is an instance of NSManagedObject stored in userManager as an array, and created by a FetchRequest from a Core Data store

UserDetail is a view displaying properties of user, accessing userManager through @EnvironmentObject.

I have tried adding the id:.id and id:.self to the ForEach loop and did not work, I started with passing the userManager in as an @ObservedObject but that did not work either.

I want to keep this view structure because it displays my data nicely the way I want it in the UI, just does not update when the user property is changed.

I am just learning SwiftUI, I am sure I am missing something obvious but I cannot figure it out after searching.

I am attaching code snippets below:

var body: some View {
    NavigationView {
        List {
            
            Section("Active Users"){
                    ForEach(userManager.activeUsers) {user in
                        NavigationLink {
                            UserDetail( user: user) //*** this updates contentview correctly when user property is updated, this prints a confirmation to the console when user property is changed. 
                            
                        } label: {
                            
                            Text(user.wrappedName)
                        }
                    }
            }
            Section("Active Users"){
                NavigationLink {
                    List {
                        ForEach(userManager.activeUsers, id:\.id) { user in

                            NavigationLink {
                            
                                    UserDetail( user: user) //** this does not update content view when same property in user is updated. I prove this by a print statement which is not called. 
                                
                            
                            } label: {
                                
                                Text(user.wrappedName)
                                
                            }

                        }
                    }
                    
                } label: {
                    Text("Last Names A through H")
                }
            
            }

Here is the beginning of my UserManager class, I am using a number of computed properties to return subsets of the users array.

class UserManager: ObservableObject{
@Published var users: [UserCore]

init() {
    self.users = [UserCore]()
}

Here is the beginning of UserDetail View:

struct UserDetail: View {
    @Environment(\.managedObjectContext) var moc
    @Environment(\.presentationMode) var presentationMode
    @EnvironmentObject var userManager: UserManager

    var user: UserCore
1
  • Please provide enough code so others can better understand or reproduce the problem. Commented Feb 10, 2022 at 0:50

1 Answer 1

1

I just figured it out!

I programmatically ask the Button that changes the user state to send an objectWillChange.send() and that forces the content view to update and gives me the functionality I want:

Button(user.isActive ? "Deactivate User" : "Activate User"){
                        
                        user.isActive.toggle()
                        userManager.objectWillChange.send() // this fixed the problem!
                        try? moc.save()
                        presentationMode.wrappedValue.dismiss()
                        
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.