Categories
Mastering Development

reload FetchedResults when changing the predicate in swiftUI

i’m building a todo app with swiftUI and Core Data.
in the listView i have a button that’ll change the predicate for the fetchrequest, but i can’t get it to work.

code in the listView

struct HomeListView: View {
    @Environment(\.managedObjectContext) var context
    @FetchRequest(fetchRequest: ItemEntity.loadItems()) var items: FetchedResults<ItemEntity>

    Text("someText")
        .onTapGesture {
            ItemEntity.predicateType.next() //next() is a method defined in core data entity class
        }

code in the core data entity class

extension ItemEntity {
    static var sortType = sort.ascending
    static var predicateType = predicate.all

    static func loadItems() -> NSFetchRequest<ItemEntity> {
        var request: NSFetchRequest<ItemEntity> = ItemEntity.fetchRequest() as! NSFetchRequest<ItemEntity>

        var predicate: NSPredicate {
        switch predicateType {
        case .all:
            return NSPredicate(format: "type = %i", 0)
        case .imur:
            return NSPredicate(format: "type = %i", 0)
        case .unimur:
            return NSPredicate(format: "type = %i", 1)
        case .imunur:
            return NSPredicate(format: "type = %i", 2)
        case .unimunur:
            return NSPredicate(format: "type = %i", 3)
        case .entry:
            return NSPredicate(format: "type = %i", 4)
        }

        request.sortDescriptors = [sortDescriptor]
        request.predicate = predicate
        return request
    }

    enum predicate {
        case all
        case imur
        case unimur
        case imunur
        case unimunur
        case entry

        mutating func next() {
            switch self {
            case .all:
                self = .imur
            case .imur:
                self = .unimur
            case .unimur:
                self = .imunur
            case .imunur:
                self = .unimunur
            case .unimunur:
                self = .entry
            case .entry:
                self = .all
            }
        }
    }
}

the idea is when user tap on the button on list view, it call the next() method and set predicateType property in ItemEntity class to another value, then the predicate property in loadItems() will update the fetchrequest, then the listview will reload.

i know there is something wrong with this approach, but i can’t figure out how to fix it.
Thanks for helping!

Leave a Reply

Your email address will not be published. Required fields are marked *