Luis Ramirez
Luis Ramirez

Reputation: 1604

Searching with NSFetchResult Controller

I've been looking on how to search using a NSFetchResultController but most post I came across are from 2 years ago. Okay I'm trying to filter the objects, which in my case are Pokemon. Here is my function I'm using.

func attemptPokemonFetch(generation: String = "1", name: String = "") {
    let context = coreData.persistentContainer.viewContext

    let request: NSFetchRequest<Pokemon> = Pokemon.fetchRequest()
    let sortByName = NSSortDescriptor(key: "id", ascending: true)
    request.sortDescriptors = [sortByName]
    request.predicate = NSPredicate(format: "generation = %@", generation)
    if !name.isEmpty {
        request.predicate = NSPredicate(format: "name CONTAINS[cd] %@", name)
    }

     let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
    controller.delegate = self
    self.controller = controller

    do {
        try controller.performFetch()
    }
    catch let err {
        print(err)
    }
}

I call this function in view did load, search bar did change text and when the segment changes index value. I know how to filter the Pokemon and use the searching. However the problem I come across is when I begin searching. When searching for a Pokemon in a specific generation other Pokemon from another generation will also appear. So I'll be at index 2 which is for generation 2 Pokemon and when searching, other Pokemon from different generation will be appearing. I'm not sure if its how I initialize the context. This is how my search bar function look like.

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchBar == pokemonSearchBar {
        let text = pokemonSearchBar.text!
        self.attemptPokemonFetch(name: text)
        collectionView.reloadData()
    }
}

Another Example: Lets say I have 3 types of people some are skinny, normal and fat. When I'm at the index for skinny people I only want to search for people that are skinny not all the people. So what would I need to do to achieve this type of behavior.

Would really appreciate any help. :)

Upvotes: 0

Views: 69

Answers (1)

Martin R
Martin R

Reputation: 539675

In your code

request.predicate = NSPredicate(format: "generation = %@", generation)
if !name.isEmpty {
    request.predicate = NSPredicate(format: "name CONTAINS[cd] %@", name)
}

the second assignment replaces the previously assigned predicate. What you probably want is

if name.isEmpty {
    request.predicate = NSPredicate(format: "generation = %@", generation)
} else {
    request.predicate = NSPredicate(format: "generation = %@ AND name CONTAINS[cd] %@", generation, name)
}

A more flexible approach is to use NSCompoundPredicate:

var predicates = [NSPredicate]()
predicates.append(NSPredicate(format: "generation = %@", generation))
if !name.isEmpty {
    predicates.append(NSPredicate(format: "name CONTAINS[cd] %@", name))
}
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)

Upvotes: 1

Related Questions