Swift Using NSFetchedResultsController and UISearchBarDelegate

前端 未结 2 1500
广开言路
广开言路 2021-02-10 17:12

I am looking for a decent solution to this problem. I am wanting to implement some simple search functionality on a TableView that I have.

All the examples I have found

相关标签:
2条回答
  • 2021-02-10 17:29

    Swift 4.2

    This is a working solutions from one of my app. I have trimmed it down to make it simple to show how it works.

    I have a database of around 6000 rows in which I search via 3 different scopes: Notes, Author and Keywords. I call initializeFetchedResultsController in the viewDidLoad function with default values. And later when user starts typing in the Search field, start calling it again with the required value.

    The Fetch part:

    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)")
        }
    }
    

    The search controller:

    // 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)
    }
    }
    

    And this in my notesSearched method which re-initialize the fetch results controller and reload the table every time.

    // MARK: - Private instance methods
    
    private func notesSearched(_ text: String, _ scope: Int) {
        initializeFetchedResultsController(text, scope)
        tableView.reloadData()
    }
    

    While calling doing so many table reloads might not be the most efficient way to do this, but it is lightening fast, and since this updates the table in real-time as user is typing it provides a wonderful user experience.

    0 讨论(0)
  • 2021-02-10 17:41

    From your code, I assume you want to use the same table view to display the results. So you just need to update your FRC with a new filter based on the search term.

    Store the search term in a variable. In the FRC factory function, include the predicate, something like this:

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

    When the text changes, reset the FRC and reload.

    fetchedResultsController = nil
    tableView.reloadData()
    

    If you have additional filters, such as scope buttons, add additional terms to the predicate.

    0 讨论(0)
提交回复
热议问题