我一直在寻找如何使用NSFetchResultController进行搜索,但我发现的大多数帖子都来自2年前。 好吧,我正在尝试过滤对象,在我的例子中是口袋妖怪。 这是我正在使用的功能。
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) } }我在视图中调用此函数加载,搜索栏确实更改了文本以及当段更改索引值时。 我知道如何过滤口袋妖怪并使用搜索。 然而,我遇到的问题是当我开始搜索时。 当在特定世代中搜索神奇宝贝时,也将出现来自另一代的其他神奇宝贝。 因此,我将在第2代口袋妖怪的索引2处,在搜索时,将出现来自不同世代的其他口袋妖怪。 我不确定它是如何初始化上下文的。 这就是我的搜索栏功能的样子。
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { if searchBar == pokemonSearchBar { let text = pokemonSearchBar.text! self.attemptPokemonFetch(name: text) collectionView.reloadData() } }另一个例子:假设我有3种类型的人,有些是瘦的,正常的和胖的。 当我在瘦人的索引时,我只想搜索那些瘦弱的人而不是所有的人。 那么我需要做些什么才能实现这种行为。
非常感谢任何帮助。 :)
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. :)
最满意答案
在你的代码中
request.predicate = NSPredicate(format: "generation = %@", generation) if !name.isEmpty { request.predicate = NSPredicate(format: "name CONTAINS[cd] %@", name) }第二个赋值替换先前分配的谓词。 你可能想要的是什么
if name.isEmpty { request.predicate = NSPredicate(format: "generation = %@", generation) } else { request.predicate = NSPredicate(format: "generation = %@ AND name CONTAINS[cd] %@", generation, name) }更灵活的方法是使用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)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)更多推荐
发布评论