为 UISearchBar 设置的谓词更新 fetchedResultsController
Updating fetchedResultsController for predicate set by UISearchBar
重构为原版 UIViewController
我没有让 UITableView
在活动和不活动之间切换 UISearchController
,而是重构为顶部 UISearchBar
和 [=14] 的香草 UIViewController
=] 就在它下面。
我想做的是在具有由 searchBar 中的文本设置的谓词和抓取所有内容的谓词之间切换 fetchedResultsController
。
我找到了这个答案,它描述了 Objective-C 中类似问题的解决方案,并作为我重构 Swift 项目的基础:
如何使用 UISearchDisplayController/UISearchBar 过滤 NSFetchedResultsController (CoreData)
我的问题:如何更新 searchBar
文本的 fetchedResultsController?
tableView
正确填充,但我不知道如何为我的 searchPredicate
更新 fetchedResultsController
这就是我试过的方法。
这是我在 class 顶部声明我的 NSPredicate
& NSFetchedResultsController
的方式:
var searchPredicate = NSPredicate()
// Create fetchedResultsController to store search results
lazy var fetchedResultsController: NSFetchedResultsController = {
let fetchRequest = NSFetchRequest(entityName: "Song")
let sortDescriptor = NSSortDescriptor(key: "songDescription", ascending: true);
// ** THESE TWO LINES CAUSE A CRASH, BUT NO COMPILER ERRORS **
// let predicate = self.searchPredicate
// fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 20
let frc = NSFetchedResultsController (fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: "songDescription", cacheName: nil)
frc.delegate = self
return frc
}()
这是我的 UISearchBarDelegate
方法:
// MARK: - UISearchBarDelegate methods
// called when text changes (including clear)
internal func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
print("searchText = \(searchBar.text)")
searchPredicate = NSPredicate(format: "(songDescription contains [cd] %@) || (songStar contains[cd] %@)", searchBar.text!, searchBar.text!)
// TODO: figure out how to update fetchedResultsController w/ predicate
}
// called when cancel button pressed
internal func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.resignFirstResponder()
searchBar.text = ""
// TODO: flip back to normal fetchResultsController
}
这是我的 NSFetchedResultsControllerDelegate
方法
internal func controllerWillChangeContent(controller: NSFetchedResultsController) {
print("controllerWillChangeContent")
tableView.beginUpdates()
}
internal func controllerDidChangeContent(controller: NSFetchedResultsController) {
print("controllerDidChangeContent")
tableView.reloadData()
tableView.endUpdates()
}
internal func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
case .Delete:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
case .Update:
tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
case .Move:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
tableView.insertRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
}
}
感谢您的阅读。我欢迎你的建议。
这不是-swift-伪代码...它肯定不会用任何swift编译器编译。
您的FRC没有使用缓存,所以没有要删除的缓存,我们可以将谓词分配给现有的FRC获取请求。
您可能不想对搜索栏中的每个字符更改都进行全新的提取,或者您可能只想对第一个字符进行搜索,并对后续字符使用子集。
// called when text changes (including clear)
internal func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
var predicate:NSPredicate = nil
if searchBar.text.length != 0 {
predicate = NSPredicate(format: "(songDescription contains [cd] %@) || (songStar contains[cd] %@)", searchBar.text!, searchBar.text!)
}
fetchedResultsController.fetchRequest.predicate = predicate
fetchedResultsController.performFetch()
tableView.reloadData()
}
// called when cancel button pressed
internal func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.resignFirstResponder()
searchBar.text = ""
fetchedResultsController.fetchRequest.predicate = nil
fetchedResultsController.performFetch()
tableView.reloadData()
}
重构为原版 UIViewController
我没有让 UITableView
在活动和不活动之间切换 UISearchController
,而是重构为顶部 UISearchBar
和 [=14] 的香草 UIViewController
=] 就在它下面。
我想做的是在具有由 searchBar 中的文本设置的谓词和抓取所有内容的谓词之间切换 fetchedResultsController
。
我找到了这个答案,它描述了 Objective-C 中类似问题的解决方案,并作为我重构 Swift 项目的基础:
如何使用 UISearchDisplayController/UISearchBar 过滤 NSFetchedResultsController (CoreData)
我的问题:如何更新 searchBar
文本的 fetchedResultsController?
tableView
正确填充,但我不知道如何为我的 searchPredicate
更新 fetchedResultsController
这就是我试过的方法。
这是我在 class 顶部声明我的 NSPredicate
& NSFetchedResultsController
的方式:
var searchPredicate = NSPredicate()
// Create fetchedResultsController to store search results
lazy var fetchedResultsController: NSFetchedResultsController = {
let fetchRequest = NSFetchRequest(entityName: "Song")
let sortDescriptor = NSSortDescriptor(key: "songDescription", ascending: true);
// ** THESE TWO LINES CAUSE A CRASH, BUT NO COMPILER ERRORS **
// let predicate = self.searchPredicate
// fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 20
let frc = NSFetchedResultsController (fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: "songDescription", cacheName: nil)
frc.delegate = self
return frc
}()
这是我的 UISearchBarDelegate
方法:
// MARK: - UISearchBarDelegate methods
// called when text changes (including clear)
internal func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
print("searchText = \(searchBar.text)")
searchPredicate = NSPredicate(format: "(songDescription contains [cd] %@) || (songStar contains[cd] %@)", searchBar.text!, searchBar.text!)
// TODO: figure out how to update fetchedResultsController w/ predicate
}
// called when cancel button pressed
internal func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.resignFirstResponder()
searchBar.text = ""
// TODO: flip back to normal fetchResultsController
}
这是我的 NSFetchedResultsControllerDelegate
方法
internal func controllerWillChangeContent(controller: NSFetchedResultsController) {
print("controllerWillChangeContent")
tableView.beginUpdates()
}
internal func controllerDidChangeContent(controller: NSFetchedResultsController) {
print("controllerDidChangeContent")
tableView.reloadData()
tableView.endUpdates()
}
internal func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
case .Delete:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
case .Update:
tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
case .Move:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
tableView.insertRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
}
}
感谢您的阅读。我欢迎你的建议。
这不是-swift-伪代码...它肯定不会用任何swift编译器编译。
您的FRC没有使用缓存,所以没有要删除的缓存,我们可以将谓词分配给现有的FRC获取请求。
您可能不想对搜索栏中的每个字符更改都进行全新的提取,或者您可能只想对第一个字符进行搜索,并对后续字符使用子集。
// called when text changes (including clear)
internal func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
var predicate:NSPredicate = nil
if searchBar.text.length != 0 {
predicate = NSPredicate(format: "(songDescription contains [cd] %@) || (songStar contains[cd] %@)", searchBar.text!, searchBar.text!)
}
fetchedResultsController.fetchRequest.predicate = predicate
fetchedResultsController.performFetch()
tableView.reloadData()
}
// called when cancel button pressed
internal func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.resignFirstResponder()
searchBar.text = ""
fetchedResultsController.fetchRequest.predicate = nil
fetchedResultsController.performFetch()
tableView.reloadData()
}