Swift使用NSFetchedResultsController和UISearchBarDelegate

dya*_*rth 3 core-data uisearchbar ios swift

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

我发现的所有示例要么使用已弃用,UISearchDisplayController要么使用新的UISearchController但没有NSFetchedResultsController 当前这是使用Core Data/ 填充NSFetchedResultsController

到目前为止,我已经设法让它达到了我可以收集用户搜索字符串的程度(喔!).我知道我可能需要单独FRC执行搜索,但如上所述,到目前为止所有尝试都失败了.

我的班级符合以下协议:

class JobListController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate, UISearchBarDelegate{
Run Code Online (Sandbox Code Playgroud)

我无法使用,UITableViewController因为我已经编写了大量现有功能,依赖于这个类,UIViewController 我有两个IBOutlets:

@IBOutlet var tblJobs : UITableView!
@IBOutlet weak var searchBar: UISearchBar!
Run Code Online (Sandbox Code Playgroud)

和我的空数组,以保持我的各种Core Data位和bobs:

var workItems = [Work]()
var filteredWorkItems = [Work]()
Run Code Online (Sandbox Code Playgroud)

以下是我初始化我的方式FRC,以及我MOC和我已经离开的空白,FRC因为我很确定在某些时候需要它:

  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?
Run Code Online (Sandbox Code Playgroud)

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

  tblJobs.delegate = self
  tblJobs.dataSource = self
  searchBar.delegate = self
Run Code Online (Sandbox Code Playgroud)

searchBar这是我能够胜任的功能.该stringMatch变量是先前尝试的剩余变量,我希望能够在这里通过多种不同的参数进行搜索,但是如果我只能使用一个参数,那将是一个可靠的开始.

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()
}
Run Code Online (Sandbox Code Playgroud)

这是我的cellForRowAtIndexPath功能,以显示我如何从中提取数据fetchedResultsController

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
}
Run Code Online (Sandbox Code Playgroud)

所以你可以看到我在这里发生了一些事情,最终我想知道我如何使用我新获得的searchText字符串来查询我FRC,然后在View中正确过滤结果.

更新:

我试图将搜索字符串添加到我的NSPredicate中,FRC所以:

lazy var fetchedResultsController: NSFetchedResultsController = {

   ../


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

   //...
    return frc
    }()
Run Code Online (Sandbox Code Playgroud)

结果如何 'JobListController.Type' does not have a member named 'savedSearchTerm'

在我的班级的顶部,我已经设置了这样:

var savedSearchTerm: NSString?
Run Code Online (Sandbox Code Playgroud)

所以不确定我做错了什么?

Mun*_*ndi 8

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

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

request.predicate = searchText?.characters.count > 0 ?
 NSPredicate(format:"title contains[cd] %@", searchText!) : nil
Run Code Online (Sandbox Code Playgroud)

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

fetchedResultsController = nil
tableView.reloadData()
Run Code Online (Sandbox Code Playgroud)

如果您有其他过滤器(例如范围按钮),请在谓词中添加其他术语.

  • 您不必将NSFetchedResultsController设置为nil.使用以下命令重置谓词:fetchedResultsController.fetchRequest.predicate.然后调用self.fetchedResultsController.performFetch(&error)来重新查询. (4认同)