【问题标题】:Updating fetchedResultsController for predicate set by UISearchBar为 UISearchBar 设置的谓词更新 fetchedResultsController
【发布时间】:2016-01-29 00:27:46
【问题描述】:

重构为原版UIViewController

我没有让UITableView 在活动和非活动UISearchController 之间切换,而是重构为一个香草UIViewController,顶部是UISearchBar,正下方是UITableView

我想要做的是在fetchedResultsController 之间切换具有由搜索栏中的文本设置的谓词和抓取所有内容的谓词。

我找到了这个答案,它描述了 Objective-C 中类似问题的解决方案,并作为我重构 Swift 项目的基础:

如何使用 UISearchDisplayController/UISearchBar 过滤 NSFetchedResultsController (CoreData) https://stackoverflow.com/a/9512891/4475605

我的问题:如何为 searchBar 文本更新 fetchedResultsController?

tableView 填充正确,但我不知道如何为我的searchPredicate 更新fetchedResultsController 这是我尝试过的。

这是我在班级顶部声明我的NSPredicateNSFetchedResultsController 的方式:

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 uitableview core-data nspredicate nsfetchedresultscontroller


    【解决方案1】:

    这不是那么快速的伪代码......它肯定不会用任何 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()
    }
    

    【讨论】:

    • 感谢您让我越过终点线!我从这篇帖子stackoverflow.com/a/32073151/4475605 中找到了搜索的方法,但是当我尝试输入nil 时,取消搜索让我失去了 b/c 自动完成功能,提示 fetchedResultsController.fetchRequest.predicate = NilLiteralConvertible!我输入了 nil,剩下的就交给我了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-13
    相关资源
    最近更新 更多