1

I have a Greek dictionary app that searches tens of thousands of word entries from Sqlite to fill a UITableView. I'm encountering many of the same problems outlined here (keyboard lag as search text changes & needing to abort search and rerun if search text changes), and the solution provided works great.

My code:

func updateSearchResultsForSearchController(searchController: UISearchController) {
    if (self.resultSearchController.searchBar.text == "") {
        theResultsArray.removeAll(keepCapacity: true)
        searchTable.reloadData()
        return
    }
    self.theResultsArray = filter(self.wordArray) {
        $0[self.betaNoSymbols].rangeOfString(self.resultSearchController.searchBar.text) != nil
        // ($0[self.betaCode] as NSString).containsString(self.resultSearchController.searchBar.text)
    }
    searchTable.reloadData()
}

In the current example, I'm searching only one field but I'd like to search multiple, the Greek word with and without diacritics, and beta code (transliterated english) with and without symbols. I'm wondering if it'd be faster to query Sqlite or first place the word list in an Array, and if there's another solution with Swift and iOS 8. If I should adapt the code, help would be appreciated.

Update:

I've put the search in an async queue and it seems to be working. Using an array filter, the search for some reason stopped working after a bunch of edits to the UISearchBar, so it's now using Sqlite.

let searchQueue = dispatch_queue_create("searchQueue", DISPATCH_QUEUE_SERIAL)

func updateSearchResultsForSearchController(searchController: UISearchController) {

    if (self.resultSearchController.searchBar.text == "") {
        theResultsArray.removeAll(keepCapacity: true)
        searchTable.reloadData()
        println("Search field empty.")
        return
    }

    let searchText = self.resultSearchController.searchBar.text

    var tempArray = [Row]()
    dispatch_async(searchQueue) {

        // abort if text changed
        if searchText != self.resultSearchController.searchBar.text {
            println("Search changed, aborted.")
            return
        }

        // do search
        if resultSearchController.searchBar.selectedScopeButtonIndex == 0 {
            tempArray = Array(self.liddellQuery.select(self._id, self.greekFullWord).filter(
                like("%\(self.resultSearchController.searchBar.text!)%", self.betaNoSymbols)
                || like("%\(self.resultSearchController.searchBar.text!)%", self.betaSymbols)
                || like("%\(self.resultSearchController.searchBar.text!)%", self.greekFullWord)
                || like("%\(self.resultSearchController.searchBar.text!)%", self.greekLowercase)
                || like("%\(self.resultSearchController.searchBar.text!)%", self.greekNoSymbols)                println("Searched: \(self.resultSearchController.searchBar.text), results: \(tempArray.count)")
        } else {
           ...
        }
        // update if search still current
        if searchText == self.resultSearchController.searchBar.text {
            dispatch_async(dispatch_get_main_queue()) {
                self.theResultsArray = tempArray
                self.searchTable.reloadData()
            }
        }
    }
}

I'm not sure if as is is the best way. There is also a long delay between searches and an UIIndicatorView to replace the search icon would be helpful.

Community
  • 1
  • 1
empedocle
  • 1,862
  • 1
  • 14
  • 25

0 Answers0