Post

CoreData y NSCompoundPredicate

En mi proyecto final del Swift Full Stack Bootcamp de Apple Coding Academy, quería que el usuario pudiera filtrar por tags los encuentros que puede obtener. Para ello tenía que actualizar el @FetchRequest cada vez que el usuario pulsaba una tag.

💡Descubrí que existe NSCompoundPredicate: un array de NSPredicate en el que se puede definir un tipo lógico como and, or o not.

Así que añadí una static func a NSPredicate (1).

extension NSPredicate {
    static func encuentrosBy (tags: [TagEntity]) -> NSPredicate {
        let tagNames = tags.map (\.nameView)
        var subPredicates: [NSPredicate] = [.encuentrosUnpurchased]
        for tagName in tagNames {
            let predicate = NSPredicate(format: "ANY %K == %",argumentArray: ["tagEntities.name", tagName])
            subPredicates.append (predicate)
            
            return NSCompoundPredicate(type: .and, subpredicates: subPredicates)
        }
    }
}

Para poder llamarla desde la subvista (2)

ForEach(tags) { tag in
    Button {
        selectedTags.append(tag)
        tagsPredicate(.encuentrosBy(tags:selectedTags))
    } label: {
        Text(tag.nameView)
        modifier (FootnoteTextModifier(color: selectedTags.contains(tag) ?.red
                                       : .gray))
    }
    .buttonStyle(.bordered)
}
.onChange (of: selectedTags) {_, newValue in
    filterTags(&selectedTags)
}

Y se muestre la barra si el usuario desea filtrar por tags (3), pasando el nuevo NSPredicate.

.toolbar
ToolbarItem (placement: .principal) {
    buildIf(unpurchasedVM.showFilterTags) {
        TagFilterView() { predicate in
            encuentros.nsPredicate = predicate
        }
    }
}