SwiftUI - how to update data with fetchRequest in init

断了今生、忘了曾经 提交于 2020-12-08 02:17:30

问题


I am doing a CoreData fetch inside my init() method of the View. I am not using FetchRequest in SwiftUI, as I need a predicate based on a parameter which is send to the View aswell. Using that parameter in the @FetchRequest will cause an error, as the variable has not been initialized.

I am doing following fetch Request inside the init()

//FetchRequest
let fetch : NSFetchRequest<Article>
self.articleRows = [Article]()
fetch = Article.fetchRequest() as! NSFetchRequest<Article>
fetch.predicate = NSPredicate(format: "type == %d", self.type)

do {
    self.articleRows = try NSManagedObjectContext.current.fetch(fetch)
} catch
{
}

That is working fine. I am displaying all my data inside a ForEach loop.

ForEach(self.articleRows, id:\.self) { article in

However, when I am deleting an entity from my context I need to refresh the view to display the changes. On delete action I toggle a @State variable, to refresh the view. That works, however the entity is still inside my Array. Thats due to the fact that init() is not called again and the fetch request is not made again. If init() would be called, the deleted entity wouldn't be there anymore.

What is the best approach here? How can I refetch my CoreData entities.

My current solution: I am currently using a Binding inside my Fetch view. If I make changes I toggle that binding and my parent view reloads. The will cause my child view (fetch View) to reload aswell and the fetch request is made again. Is that the best way? Any simpler solution for that?


回答1:


So, I found a way of solving my problem.

What was the problem?

The View was not updating because I wasn't using FetchRequest property wrapper, because I need a instance variable in that FetchRequest. So I need to do the Fetching inside my Init() method. But what I did was, I just fetched my items once in the init() and that won't be updated unless the parent with is reloaded.

How to solve it without annoying parent update?

Instead of doing a manual fetch only once in the init() I used a FetchRequest and initialized it in the init(), so it still behaves as FetchRequest property wrapper, like an Observable Object.

I declared it like that:

@FetchRequest var articleRows : FetchedResults<Article>

And inside the init()

//Here in my predicate I use self.type variable 
var predicate = NSPredicate(format: "type == %d", self.type)

//Intialize the FetchRequest property wrapper
self._articleRows = FetchRequest(entity: Article.entity(), sortDescriptors: [], predicate: predicate)



回答2:


Assuming you have your managedObjectContext set up as such;

@Environment(\.managedObjectContext) var moc

then I believe this solution might work for you.

func deleteArticle(at index: IndexSet) {
    for i in index {
        // pull the article from the FetchRequest
        let article = articleRows[i]
        moc.delete(article)
    }
    // resave to CoreData
    try? moc.save()
}

call that method at the end of your ForEach block with;

.onDelete(perform: deleteArticle)

That said I am not familiar with the way you are doing the fetch request so you made need to do some tweaking.

  • Dan


来源:https://stackoverflow.com/questions/62636252/swiftui-how-to-update-data-with-fetchrequest-in-init

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!