首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快速使用NSFetchedResultsController和UISearchBarDelegate

快速使用NSFetchedResultsController和UISearchBarDelegate
EN

Stack Overflow用户
提问于 2015-08-18 12:41:08
回答 2查看 3.3K关注 0票数 4

我正在寻找一个体面的解决这个问题的办法。我想在我拥有的TableView上实现一些简单的搜索功能。

我找到的所有示例要么使用不推荐的UISearchDisplayController,要么使用新的UISearchController,但目前没有NSFetchedResultsController,这是使用Core Data / NSFetchedResultsController填充的。

到目前为止,我已经成功地实现了一个可以收集用户搜索字符串(woo!)的点。我知道我可能需要一个单独的FRC来执行搜索,但正如前面提到的,到目前为止所有的尝试都失败了。

我的班级遵循以下协议:

代码语言:javascript
复制
class JobListController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate, UISearchBarDelegate{

我不能使用UITableViewController,因为我已经编写了大量现有的功能,这些功能依赖于这个类是一个UIViewController,我有两个IBOutlets

代码语言:javascript
复制
@IBOutlet var tblJobs : UITableView!
@IBOutlet weak var searchBar: UISearchBar!

以及我的空数组来保存我的各种Core Data位和bobs:

代码语言:javascript
复制
var workItems = [Work]()
var filteredWorkItems = [Work]()

下面是我如何初始化我的FRC,以及我的MOC和我的空的第二个FRC,因为我确信在某个时候它是必要的:

代码语言:javascript
复制
  let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

lazy var fetchedResultsController: NSFetchedResultsController = {
    let workFetchRequest = NSFetchRequest(entityName: "Work")
    let primarySortDescriptor = NSSortDescriptor(key: "createdDate", ascending: true)
    let secondarySortDescriptor = NSSortDescriptor(key: "town", ascending: true)
    workFetchRequest.sortDescriptors = [primarySortDescriptor, secondarySortDescriptor]

    let frc = NSFetchedResultsController(
        fetchRequest: workFetchRequest,
        managedObjectContext: self.managedObjectContext!,
        sectionNameKeyPath: "createdDate",
        cacheName: nil)

    frc.delegate = self


    return frc
    }()

var searchResultsController: NSFetchedResultsController?

在我的viewDidLoad函数中,我正在设置表和searchBar的委托/数据源:

代码语言:javascript
复制
  tblJobs.delegate = self
  tblJobs.dataSource = self
  searchBar.delegate = self

这是searchBar函数,这就是我要做的。stringMatch变量是前一次尝试中遗留下来的,我希望能够在这里通过多种不同的参数进行搜索,但是如果我能够只使用一个参数,这将是一个坚实的开端。

代码语言:javascript
复制
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
    println("Search text is \(searchText)")
    self.filteredWorkItems = self.workItems.filter({( work: Work) -> Bool in
        //
        let stringMatch = work.postcode.rangeOfString(searchText)
        return stringMatch != nil
    })

    if(filteredWorkItems.count == 0){
        searchActive = false;
    } else {
        searchActive = true;
    }
    self.tblJobs.reloadData()
}

下面是我的cellForRowAtIndexPath函数,显示如何从fetchedResultsController中提取数据

代码语言:javascript
复制
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
    let cell =  self.tblJobs.dequeueReusableCellWithIdentifier(
        "JobCell", forIndexPath: indexPath)
        as! JobTableViewCell

    let workItem = fetchedResultsController.objectAtIndexPath(indexPath) as! Work



 //...

    return cell
}

因此,您可以看到,我在这里做了一些事情,最终我想弄清楚如何使用新获得的searchText字符串来查询我的FRC,然后在视图中对结果进行适当的过滤。

更新:

我尝试将搜索字符串添加到FRC中的FRC中,如下所示:

代码语言:javascript
复制
lazy var fetchedResultsController: NSFetchedResultsController = {

   ../


    workFetchRequest.predicate = NSPredicate(format:"title contains[cd] %@", savedSearchTerm!)

   //...
    return frc
    }()

这导致了'JobListController.Type' does not have a member named 'savedSearchTerm'

在我班的第一名,我把它设成这样:

代码语言:javascript
复制
var savedSearchTerm: NSString?

所以不知道我做错了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-18 12:59:35

从您的代码中,我假设您希望使用相同的表视图来显示结果。因此,您只需更新您的FRC与一个新的过滤器,基于搜索词。

将搜索项存储在变量中。在FRC工厂函数中,包括谓词,如下所示:

代码语言:javascript
复制
request.predicate = searchText?.characters.count > 0 ?
 NSPredicate(format:"title contains[cd] %@", searchText!) : nil

当文本更改时,重置FRC并重新加载。

代码语言:javascript
复制
fetchedResultsController = nil
tableView.reloadData()

如果您有其他筛选器(如范围按钮),则向谓词添加其他术语。

票数 10
EN

Stack Overflow用户

发布于 2019-02-09 18:33:42

Swift 4.2

这是我的一个应用程序的解决方案。我已经对它进行了精简,以使它简单地显示它是如何工作的。

我有一个大约6000行的数据库,其中我通过三个不同的范围进行搜索: Notes、Author和关键字。我用默认值在initializeFetchedResultsController函数中调用viewDidLoad。稍后,当用户开始键入搜索字段时,使用所需的值再次调用它。

提取部分:

代码语言:javascript
复制
let EMPTY_STRING = "" // I don't like string literals in my code so define them as static variables separately

// Giving two default values
func initializeFetchedResultsController(_ text: String: EMPTY_STRING, _ scope: Int = 0) {
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: NotesAttributes.author.rawValue, ascending: true)]
            if searchedStringTemp != EMPTY_STRING { // Whatever conditions you want to pass on
                let p0 = NSPredicate(format: NotesAttributes.scope.rawValue + " != \(scope)")
                let p1 = NSPredicate(format: "\(column) CONTAINS[cd] %@", "\(text)")
                fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [p0, p1])
            }

    fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: AppDelegate().sharedInstance().persistentContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil)
    fetchedResultsController.delegate = self

    do {
        try self.fetchedResultsController.performFetch()
    } catch {
        let fetchError = error as NSError
        print("Error 12312: Unable to Perform Fetch Request")
        print("\(fetchError), \(fetchError.localizedDescription)")
    }
}

搜索控制器:

代码语言:javascript
复制
// MARK: - UISearchBar Delegate
extension AllNotesVC: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
    // This is my function which I call to start search
    notesSearched(searchBar.text!, searchBar.scopeButtonTitles![selectedScope])
}
}

// MARK: - UISearchResultsUpdating Delegate
extension AllNotesVC: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
    let text = searchController.searchBar.text!
    let searchBar = searchController.searchBar
    let scope = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex]
    // This is my function which I call to start search
    notesSearched(text, scope)
}
}

在我的notesSearched方法中,每次重新初始化获取结果控制器并重新加载表。

代码语言:javascript
复制
// MARK: - Private instance methods

private func notesSearched(_ text: String, _ scope: Int) {
    initializeFetchedResultsController(text, scope)
    tableView.reloadData()
}

虽然调用这么多表重新加载可能不是最有效的方法,但它是闪电快速,因为这是实时更新的表,因为用户正在打字,它提供了一个很好的用户体验。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32072723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档