Home > Net >  SwiftUI: trigger redraw when NSManagedObject (not part of fetch request) bool property changes?
SwiftUI: trigger redraw when NSManagedObject (not part of fetch request) bool property changes?

Time:04-30

I have the following @SectionedFetchRequest installed on my SwiftUI view:

@SectionedFetchRequest(entity: Car.entity(),
                       sectionIdentifier: \.dealer.name,
                       sortDescriptors: [
                        NSSortDescriptor(key: "\(#keyPath(Car.dealer.name))", ascending: true),
                        NSSortDescriptor(key: "\(#keyPath(Car.milage))", ascending: true),
                       ]
                       , predicate: nil,
                       animation: .default)
var carsResult: SectionedFetchResults<String, Car>

In the view, I have this:

LazyVStack {
                                    
    ForEach(carsResult) { section in
                        
        if let dealer = section.first?.dealer {
                            
            Section(header:  DealerSHView(dealer: dealer)) {

                if dealer.isOpen {
                     ForEach(section) { channel in
                         ....
                     }
                } else {
                     ....
                }

            }
                            
        }
                        
    }
}

When a button is pressed on the DealerSHView, the dealer.isOpen boolean is toggled. Dealer is a NSManagedObject, like Car is.

Problem: the view does not update, specifically this part:

            if dealer.isOpen {
                 ForEach(section) { channel in
                     ....
                 }
            } else {
                 ....
            }

has no effect, it just runs the case that is detected at first render, but not when isOpen changes and it's saved to disk via core data save.

Question: How can I get the view to react and redraw when isOpen changes?

CodePudding user response:

Move it all into a sub-View and use @ObservedObject like this:

struct DealerSection : View {
    @ObservedObject var dealer: Dealer // body will be called when dealer changes.

    var body: some View {
        Section(header:  DealerSHView(dealer: dealer)) {

            if dealer.isOpen {
                 ForEach(section) { channel in
                     ....
                 }
            } else {
                 ....
            }

         }
    }

Then in your parent View's body it's just:

ForEach(carsResult) { section in
                        
        if let dealer = section.first?.dealer {
                            
            DealerSection(dealer: dealer)
                            
        }
                        
    }
  • Related