swiftcore-dataswiftuinspredicatensfetchrequest

@FetchRequest predicate not updating when UserDefaults value changes SwiftUI


I'm having trouble figuring out how to make a SwiftUI @FetchRequest use a predicate only if a Boolean value stored in UserDefaults is true .

The issue is that the FetchedResults is not changing when the value for showAvailable changes. Currently I have to relaunch the app to see the showAvailable value based results.

struct ContentView: View {

@AppStorage("showAvailable") private var showAvailable : Bool = false


@FetchRequest private var list: FetchedResults<Item>



init() {
        @AppStorage("showAvailable") var showAvailable : Bool = false
        _list = FetchRequest(
            sortDescriptors: [],
            predicate: showAvailable ? NSPredicate(format: "parent == nil") : nil,
            animation: .default
        )
}

var body: some View {
     Button("Cancel") {
        showAvailable.toggle()
     }
}

Solution

  • I would update the fetch request with a new predicate in the Button action and that update should trigger the request to be executed again

    struct ContentView: View {
        @AppStorage("showAvailable") private var showAvailable : Bool = false
    
        @FetchRequest(sortDescriptors: [], 
                      predicate: NSPredicate(value: true)
                      animation: .default)
        private var list: FetchedResults<Item>
    
        var body: some View {
            Button("Cancel") {
                showAvailable.toggle()
                updatePredicate()
            }
            .onAppear {
                updatePredicate()
            }
        }
    
        private func updatePredicate() {
            if showAvailable {
                list.nspredicate = NSPredicate(format: "parent == nil")
            } else {
                list.nspredicate = NSPredicate(value: true)
            }        
        }
    }