Ускорьте UISearchController с помощью потоков

У меня есть приложение греческого словаря, которое ищет десятки тысяч слов из Sqlite, чтобы заполнить UITableView. Я сталкиваюсь со многими из тех же проблем, которые описаны здесь (задержка клавиатуры при изменении текста поиска и необходимость прерывания поиска и повторного запуска при изменении текста поиска), и предоставленное решение отлично работает.

Мой код:

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

В текущем примере я ищу только одно поле, но я хотел бы искать несколько, греческое слово с диакритическими знаками и без них, а также бета-код (транслитерированный английский) с символами и без них. Мне интересно, будет ли быстрее запрашивать Sqlite или сначала помещать список слов в массив, и есть ли другое решение с Swift и iOS 8. Если мне следует адаптировать код, помощь будет оценена.

Обновление:

Я поставил поиск в асинхронную очередь, и, похоже, он работает. Используя фильтр массива, поиск по какой-то причине перестал работать после множества правок в UISearchBar, поэтому теперь он использует 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()
            }
        }
    }
}

Я не уверен, что это лучший способ. Между поисками также существует большая задержка, и было бы полезно использовать UIIndicatorView для замены значка поиска.


person empedocle    schedule 28.06.2015    source источник