UISearchController仅返回第一个结果,但Core Data有几个结果

时间:2015-07-17 13:55:59

标签: swift core-data uisearchcontroller

我有UISearchController并且它只返回第一个结果,但Core Data有几个结果。

我做了很多不同的变种,但他们没有帮助我。

否则UISearchController会返回错误的结果。

import UIKit
import Foundation
import CoreData

class SongTableVC: UITableViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate, UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating {

    // MARK: - var and let
    var appDel = (UIApplication.sharedApplication().delegate as! AppDelegate)
    var context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!


    // MARK: - NSFetchedResultsController and its functions
    var fetchedResultsController: NSFetchedResultsController!

    func returnRequest() -> NSFetchRequest {
        var fetchRequest = NSFetchRequest(entityName: "Song")
        var sort = NSSortDescriptor(key: "songName", ascending: false)
        fetchRequest.fetchBatchSize = 50
        fetchRequest.predicate = nil
        fetchRequest.sortDescriptors = [sort]
        return fetchRequest
    }

    // MARK: - UISearchController and its fucntions
    var searchController: UISearchController!
    var searchPredicate: NSPredicate!
    var dataFiltered: [Song]? = nil

    func updateSearchResultsForSearchController(searchController: UISearchController) {
        var searchText = searchController.searchBar.text
        searchPredicate = NSPredicate(format: "songName contains[c] %@", searchText)
        dataFiltered = self.fetchedResultsController?.fetchedObjects?.filter(){
            return self.searchPredicate!.evaluateWithObject($0)
        } as! [Song]?
        self.tableView.reloadData()
        println(searchPredicate)
    }

    func searchBar(searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
        updateSearchResultsForSearchController(searchController)
    }

    func didDismissSearchController(searchController: UISearchController) {
        searchPredicate = nil
        dataFiltered = nil
        self.tableView.reloadData()
    }



    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationItem.leftBarButtonItem = self.editButtonItem()

        fetchedResultsController = NSFetchedResultsController(fetchRequest: returnRequest(), managedObjectContext: context, sectionNameKeyPath: "songName", cacheName: "songName")
        fetchedResultsController.delegate = self
        fetchedResultsController.performFetch(nil)

        searchController = ({
            var controllerSearch = UISearchController(searchResultsController: nil)
            controllerSearch.delegate = self
            controllerSearch.searchBar.delegate = self
            controllerSearch.searchBar.sizeToFit()
            controllerSearch.definesPresentationContext = false // default false
            controllerSearch.hidesNavigationBarDuringPresentation = true
            controllerSearch.searchResultsUpdater = self
            controllerSearch.dimsBackgroundDuringPresentation = false 
            self.tableView.tableHeaderView = controllerSearch.searchBar
            return controllerSearch
        })()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Potentially incomplete method implementation.
        // Return the number of sections.
        if searchPredicate == nil {
            return fetchedResultsController?.sections?.count ?? 0
        } else {
            return 1 ?? 0
        }
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searchPredicate == nil {
            return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
        } else {
            return dataFiltered?.count ?? 0
        }
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("songID", forIndexPath: indexPath) as! UITableViewCell

        if searchPredicate == nil {
            if var dataForCell = fetchedResultsController.objectAtIndexPath(indexPath) as? Song {
                cell.textLabel?.text = dataForCell.songName
                cell.detailTextLabel?.text = dataForCell.songName
            } else {
                if var dataFilterForCell = dataFiltered?[indexPath.row] {
                    cell.textLabel?.text = dataFilterForCell.songName
                    cell.textLabel?.text = dataFilterForCell.songName
                }
            }
        }
        return cell
    }


    // Override to support conditional editing of the table view.
    override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return NO if you do not want the specified item to be editable.
        return true
    }

    // Override to support editing the table view.
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            context.deleteObject(fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject)
            context.save(nil)
        } else if editingStyle == .Insert {
            context.insertObject(fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject)
            context.save(nil)
        }    
    }

    func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
        var tableView = UITableView()
        if searchPredicate == nil {
            tableView = self.tableView
        } else {
            tableView = (searchController.searchResultsController as! SongTableVC).tableView
        }

        switch type {
        case NSFetchedResultsChangeType.Insert:
            tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Delete:
            tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Move:
            tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Update:
            break
        default: break
        }
    }

    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
        var tableView = UITableView()
        if searchPredicate == nil {
            tableView = self.tableView
        } else {
            tableView = (searchController.searchResultsController as! SongTableVC).tableView
        }

        switch type {
        case NSFetchedResultsChangeType.Insert:
            tableView.insertRowsAtIndexPaths([AnyObject](), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Delete:
            tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!) as [AnyObject], withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Move:
            tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!) as [AnyObject], withRowAnimation: UITableViewRowAnimation.Fade)
            tableView.insertRowsAtIndexPaths(NSArray(object: indexPath!) as [AnyObject], withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Update:
            tableView.cellForRowAtIndexPath(indexPath!)
            break
        default: break
        }
    }

    func controllerWillChangeContent(controller: NSFetchedResultsController) {
        if searchPredicate == nil {
            tableView.beginUpdates()
        } else {
           (searchController.searchResultsController as? SongTableVC)?.tableView.beginUpdates()
        }
    }

    func controllerDidChangeContent(controller: NSFetchedResultsController) {
        if searchPredicate == nil {
            tableView.endUpdates()
        } else {
            (searchController.searchResultsController as? SongTableVC)?.tableView.endUpdates()
        }
    }

    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "add" {
            searchController.active == false

        }
    }

}

enter image description here enter image description here

1 个答案:

答案 0 :(得分:0)

我找到了问题的解决方案

import UIKit
import Foundation
import CoreData

class SongTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate, UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating {

    // MARK: - var and lets
    var appDel = (UIApplication.sharedApplication().delegate as! AppDelegate)
    var context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!

    override func viewDidLoad() {
        super.viewDidLoad()
        fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: context, sectionNameKeyPath: "nameSong", cacheName: "nameSong")
        fetchedResultsController.delegate = self
        fetchedResultsController.performFetch(nil)

        self.navigationItem.leftBarButtonItem = self.editButtonItem()

        searchController = ({
            var controllerSearch = UISearchController(searchResultsController: nil)
            controllerSearch.delegate = self
            controllerSearch.searchBar.delegate = self
            controllerSearch.hidesNavigationBarDuringPresentation = true
            controllerSearch.definesPresentationContext = false
            controllerSearch.dimsBackgroundDuringPresentation = false
            controllerSearch.searchBar.sizeToFit()
            controllerSearch.searchResultsUpdater = self
            self.tableView.tableHeaderView = controllerSearch.searchBar
            return controllerSearch
        })()

        // 
        println(path)
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        searchPredicate = nil
        filteredData = nil
        self.tableView.reloadData()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - NSFetchedResultsController and its functions
    var fetchedResultsController: NSFetchedResultsController!

    func fetchRequest() -> NSFetchRequest {
        var fetchRequest = NSFetchRequest(entityName: "Song")
        var sort = NSSortDescriptor(key: "nameSong", ascending: false)
        fetchRequest.fetchBatchSize = 50
        fetchRequest.predicate = nil
        fetchRequest.sortDescriptors = [sort]
        return fetchRequest
    }

    // MARK: - UISearchController and its functions
    var searchController: UISearchController!
    var searchPredicate: NSPredicate!
    var filteredData: [Song]? = nil

    func updateSearchResultsForSearchController(searchController: UISearchController) {
        var searchText = searchController.searchBar.text
        if searchText != nil {
            searchPredicate = NSPredicate(format: "nameSong contains[c] %@", searchText)
            filteredData = fetchedResultsController.fetchedObjects!.filter() {
                return self.searchPredicate.evaluateWithObject($0)
            } as? [Song]
            self.tableView.reloadData()
        }
    }

    func searchBar(searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
        updateSearchResultsForSearchController(searchController)
    }

    func didDismissSearchController(searchController: UISearchController) {
        searchPredicate = nil
        filteredData = nil
        self.tableView.reloadData()
    }

    // MARK: - Files from shared folder

    var fileManager = NSFileManager.defaultManager()


    var path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)



    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        if searchPredicate == nil {
            return fetchedResultsController?.sections?.count ?? 0
        } else {
            return 1 ?? 0
        }
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searchPredicate == nil {
            return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
        } else {
            return filteredData?.count ?? 0
        }
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("songID", forIndexPath: indexPath) as! UITableViewCell

        if searchPredicate == nil {
            if var dataForCell = fetchedResultsController?.objectAtIndexPath(indexPath) as? Song {
                cell.textLabel?.text = dataForCell.nameSong
            }
        } else {
            if var filteredSearch = filteredData?[indexPath.row] {
                cell.textLabel?.text = filteredSearch.nameSong
            }
        }

        return cell
    }

    // Override to support conditional editing of the table view.
    override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return NO if you do not want the specified item to be editable.
        return true
    }

    // Override to support editing the table view.
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            context.deleteObject(fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject)
            context.save(nil)
        } else if editingStyle == .Insert {
            context.insertObject(fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject)
            context.save(nil)
        }    
    }

    func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
        switch type {
        case NSFetchedResultsChangeType.Insert:
            tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Delete:
            tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Move:
            tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Update:
            break
        default: break

        }
    }

    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
        switch type {
        case NSFetchedResultsChangeType.Insert:
            tableView.insertRowsAtIndexPaths([AnyObject](), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Delete:
            tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!) as [AnyObject], withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Move:
            tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!) as [AnyObject], withRowAnimation: UITableViewRowAnimation.Fade)
            tableView.insertRowsAtIndexPaths(NSArray(object: indexPath!) as [AnyObject], withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Update:
            tableView.cellForRowAtIndexPath(indexPath!)
            break
        default: break
        }
    }

    func controllerDidChangeContent(controller: NSFetchedResultsController) {
        tableView.endUpdates()
    }

    func controllerWillChangeContent(controller: NSFetchedResultsController) {
        tableView.beginUpdates()
    }

    /*
    // Override to support rearranging the table view.
    override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {

    }
    */

    // Override to support conditional rearranging of the table view.
    override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return NO if you do not want the item to be re-orderable.
        return true
    }

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */

}