Check on FetchRequest not working

Hi,

I have the following page (this is a simplified version) where there is a FetchRequest to get a record from CoreData based on an id. This id is obtained from some json that is stored in UserDefaults (returned by the getLodgeData method).

import SwiftUI

struct TestView: View {
    var lodge: Lodge = getLodgeData()
    @State var lodgeid: Int = -1

    var body: some View {
        TestViewPage(lodgeid: lodgeid)
            .onAppear(perform: {
                self.lodgeid = Int(lodge.LodgeID) ?? 0
        })
    }
}

struct TestViewPage: View {
    var lodgeid: Int
    @Environment(\.managedObjectContext) var managedObjectContext
    var lodge: Lodge = getLodgeData()
    @State var favourite = false

    //this gets the list
    @FetchRequest var cdlodges: FetchedResults<CDLodge>

    init(lodgeid: Int) {
        self.lodgeid = lodgeid
        self._cdlodges = FetchRequest(
            entity: CDLodge.entity(),
            sortDescriptors: [
                NSSortDescriptor(keyPath: \CDLodge.lodge, ascending: true),
            ],
            predicate: NSPredicate(format: "lodgeid == \(lodgeid)")
        )

        if cdlodges.isEmpty == false {
            //not empty so set fav to true
            favourite = true
        }
        else {
            //not a favourite so set to false
            favourite = false
        }
    }

    var body: some View {
        NavigationView {
            ScrollView {
                VStack(alignment: .leading) {
                      VStack {
                          switch favourite {
                          case false:
                              Button(action: {
                                  ///save the lodge in core data
                                  //...
                                  favourite = setFav()
                              })
                              {
                                  Image("favicon_off")
                              }
                          case true:
                              Button(action: {
                                  ///delete the lodge from Core Data
                                  //...
                              })
                              {
                                  Image("favicon_on")
                              }
                          }
                      }
                      Button(action: {
                          if cdlodges.isEmpty == false {
                              //not empty so set fav to true
                              favourite = true
                          }
                          else {
                              //not a favourite so set to false
                              favourite = false
                          }
                      }) {
                          Text("testing")
                      }
                }
                .padding()
            }///end of scrollview
            .navigationBarTitle("")
            .navigationBarHidden(true)
        } //end of navigationview
    }
}

I want to set a variable (favourite) based on if the dataset that the FetchRequest returns is empty or not.

I tried putting the check after the request, but it always comes back as empty. This is odd as I know that a row is being returned.

I added a button (marked test) that runs the same check, and that works fine so I can only sumise that the initial check is being done before the resultset is finished being populated.

Is there a way that I can do the check when the query updates? At this point I feel that I'm missing something simple, but I just can't seem to see it.

Any help would be greatly appreciated.

thanks

Answered by OOPer in 677497022

I tried putting the check after the request

Seems you put the check after initializing FetchRequest, not after the request. It is hard to predict when exactly the request is made or when the result is updated.

One possible solution would be like this:

struct TestViewPage: View {
    var lodgeid: Int
    @Environment(\.managedObjectContext) var managedObjectContext
    var lodge: Lodge = getLodgeData()
    var favourite: Bool {!cdlodges.isEmpty} //<-

    //this gets the list
    @FetchRequest var cdlodges: FetchedResults<CDLodge>

    init(lodgeid: Int) {
        self.lodgeid = lodgeid
        self._cdlodges = FetchRequest(
            entity: CDLodge.entity(),
            sortDescriptors: [
                NSSortDescriptor(keyPath: \CDLodge.lodge, ascending: true),
            ],
            predicate: NSPredicate(format: "lodgeid == \(lodgeid)")
        )
    }

    var body: some View {
        NavigationView {
            ScrollView {
                VStack(alignment: .leading) {
                      VStack {
                          switch favourite {
                          case false:
                              Button(action: {
                                  ///save the lodge in core data
                                  //...
                              })
                              {
                                  Image("favicon_off")
                              }
                          case true:
                              Button(action: {
                                  ///delete the lodge from Core Data
                                  //...
                              })
                              {
                                  Image("favicon_on")
                              }
                          }
                      }
                }
                .padding()
            }///end of scrollview
            .navigationBarTitle("")
            .navigationBarHidden(true)
        } //end of navigationview
    }
}

With checking favourite dynamically, you would get the result you want. (Though, I omitted favourite = setFav(), which I cannot guess what you want to do with it...)

Accepted Answer

I tried putting the check after the request

Seems you put the check after initializing FetchRequest, not after the request. It is hard to predict when exactly the request is made or when the result is updated.

One possible solution would be like this:

struct TestViewPage: View {
    var lodgeid: Int
    @Environment(\.managedObjectContext) var managedObjectContext
    var lodge: Lodge = getLodgeData()
    var favourite: Bool {!cdlodges.isEmpty} //<-

    //this gets the list
    @FetchRequest var cdlodges: FetchedResults<CDLodge>

    init(lodgeid: Int) {
        self.lodgeid = lodgeid
        self._cdlodges = FetchRequest(
            entity: CDLodge.entity(),
            sortDescriptors: [
                NSSortDescriptor(keyPath: \CDLodge.lodge, ascending: true),
            ],
            predicate: NSPredicate(format: "lodgeid == \(lodgeid)")
        )
    }

    var body: some View {
        NavigationView {
            ScrollView {
                VStack(alignment: .leading) {
                      VStack {
                          switch favourite {
                          case false:
                              Button(action: {
                                  ///save the lodge in core data
                                  //...
                              })
                              {
                                  Image("favicon_off")
                              }
                          case true:
                              Button(action: {
                                  ///delete the lodge from Core Data
                                  //...
                              })
                              {
                                  Image("favicon_on")
                              }
                          }
                      }
                }
                .padding()
            }///end of scrollview
            .navigationBarTitle("")
            .navigationBarHidden(true)
        } //end of navigationview
    }
}

With checking favourite dynamically, you would get the result you want. (Though, I omitted favourite = setFav(), which I cannot guess what you want to do with it...)

Check on FetchRequest not working
 
 
Q