Changing a fetch request

I'm doing a FetchRequest before the body of my page but can't add in the predicate as the id that I'm after isn't available until after self is available.

I've tried moving the query to a method triggered by a button press, but I get a segmentation fault.

Is there any way that I can add the predicate after the initial query to get my collection?

Alternatively, is there a way of passing in the id to the page direct? (Its a detail page, but its not triggered by selecting a list item)

If I hard code the id, everything works as expected, I just can't seem to get the id in the original query.

thanks

Answered by OOPer in 677344022

Your code is incomplete, so I cannot test, but can you try something like this:

struct EditSocialView: View {

    @Environment(\.managedObjectContext) var managedObjectContext
    @Environment(\.presentationMode) var presentationMode
    var lodge: Lodge = getLodgeData()

    @State var lodgeId = -1

    var body: some View {
        //...
        EditSocialList(lodgeId: lodgeId)
            .onAppear(perform: {
                self.lodgeId = lodge.id
            })
        //...
    }
}

struct EditSocialList: View {
    var lodgeId: Int
    
    //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 {
        //use `cdlodges` here...
    }
}

With separating the parts depending on FetchedResults, you may be able to initialize the FetchRequest using lodgeId.

Can you show your code?

Have this at the top:

`struct EditSocialView: View {

    @Environment(.managedObjectContext) var managedObjectContext     @Environment(.presentationMode) var presentationMode

    var lodge: Lodge = getLodgeData()

    //this gets the list from CD     @FetchRequest(         entity: CDLodge.entity(),         sortDescriptors: [             NSSortDescriptor(keyPath: \CDLodge.lodge, ascending: true),         ],         predicate: NSPredicate(format: "lodgeid == 3")     ) var cdlodges: FetchedResults

    var body: some View {`

As you can see, I have the id hardcoded as 3 the actual id that I want to use comes from the getLodgeData() method at the top (lodge.id) this function retrieves a json string from UserDefaults and converts it to an instance of Lodge.

There is a button on the page that deletes this entry from CoreData. I tried to add the FetchRequest there as I can then use predicate: NSPredicate(format: "lodgeid == (lodge.id)") but I get a segmentation error.

seem to be going around in circles where I can do what I need to do, just not where I need to do it for it to work.

thanks

Thanks for showing your code. It would be better if it were properly formatted. (As the editing feature is limited in this site, you may need to add an answer to show additional info to your question.) Anyway, I will look into it when I'm ready.

I have this at the top of the page:

struct EditSocialView: View {

    @Environment(\.managedObjectContext) var managedObjectContext
    @Environment(\.presentationMode) var presentationMode
    var lodge: Lodge = getLodgeData()

    //this gets the list
    @FetchRequest(
        entity: CDLodge.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \CDLodge.lodge, ascending: true),
        ],
        predicate: NSPredicate(format: "lodgeid == 3")
    ) var cdlodges: FetchedResults<CDLodge>

    var body: some View {

As you can see, I have the id hardcoded as 3. The actual id that I want to use is obtained from the getLodgeData() method which is called before the FetchEvent. This method pulls a json string from UserDefaults and converts it to an instance of Lodge, which gives me lodge.id

On this page, there is a button which will delete the Lodge record from CoreData. Can I either add the

predicate: NSPredicate(format: "lodgeid == \(lodge.id)")

when the button is clicked? or, can I have my FetchRequest get all of the list and then I just delete the item where the id is 3?

thanks

have just don't that as it wouldn't let me format it properly (and the comment vanished) so have repeated as best I could below. sorry. Appreciate you spending the time to look.

Accepted Answer

Your code is incomplete, so I cannot test, but can you try something like this:

struct EditSocialView: View {

    @Environment(\.managedObjectContext) var managedObjectContext
    @Environment(\.presentationMode) var presentationMode
    var lodge: Lodge = getLodgeData()

    @State var lodgeId = -1

    var body: some View {
        //...
        EditSocialList(lodgeId: lodgeId)
            .onAppear(perform: {
                self.lodgeId = lodge.id
            })
        //...
    }
}

struct EditSocialList: View {
    var lodgeId: Int
    
    //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 {
        //use `cdlodges` here...
    }
}

With separating the parts depending on FetchedResults, you may be able to initialize the FetchRequest using lodgeId.

This works great, so thanks for that and I have marked the answer as solution. However, I have managed to find a way where it doesn't work quite as I expected.

I have used the same way of doing it on another page where I'm checking to see if the result set is empty and if its not, then set a @State var to true.

I put the check in after the fetch request, but it always reports that the results are empty.

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

If I add a button to the page with the same code in, it works fine. I'm assuming that where its done after the FetchRequest, the query hasn't had chance to fill the resultset in time.

Is there a way to get the check to run on completion of the FetchRequest?

Changing a fetch request
 
 
Q