如何在 iOS swift 2 中为 uisearchbar 过滤大数组

rit*_*esh 5 arrays filter uisearchbar ios swift

我的数组中有UISearchBar超过 80000 个元素,我必须根据用户输入过滤该数组。

但是,在搜索视图中输入时,其工作速度非常慢,这意味着在键盘中输入值需要花费太多时间。

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {

    if searchText.characters.count == 0 {
        searchActive = false
    } else {
        searchActive = true;
        filtered.removeAllObjects()

        dispatch_to_background_queue {
            for sumber in self.data {
                let nameRange: NSRange = sumber.rangeOfString(searchText, options: [NSStringCompareOptions.AnchoredSearch,NSStringCompareOptions.CaseInsensitiveSearch])
                if nameRange.location != NSNotFound {
                    self.filtered.addObject(sumber)
                }
            }//end of for

            self.dispatch_to_main_queue {
                /* some code to be executed on the main queue */
                self.tableView.reloadData()
            }
        } //end of dispatch
    }
}

func dispatch_to_main_queue(block: dispatch_block_t?) {
    dispatch_async(dispatch_get_main_queue(), block!)
}

func dispatch_to_background_queue(block: dispatch_block_t?) {
    let q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
    dispatch_async(q, block!)
}
Run Code Online (Sandbox Code Playgroud)

Eik*_*iko 4

我想补充一些想法。

您似乎已经进行了异步处理,这很棒。它不会使搜索更快,但应用程序会保持响应。考虑让它停止。如果用户输入三个字母,您将排队三个搜索,并且只有在最后一次运行完成后才能获得相关结果。这可以使用某种在搜索中检查的布尔停止标志来完成。如果开始新的搜索,请先杀死旧的。

显示部分结果。用户不会同时观看数千个单元,而只会观看前 20 个左右。根据输入和输出的顺序,这可能非常容易做到并且速度极快。

以您之前的搜索为基础。仅当搜索“A”(或“b”,如果搜索未锚定)也成功时,搜索“Ab”才会成功。因此,如果您上次搜索是当前搜索的子字符串,则将上次搜索的输出数组作为输入。显然,要小心这里停止的搜索。

检查性能是否真的那么糟糕。您是否在打开优化的情况下运行?调试模式可能会慢很多,但这并不重要。

数据从哪里来?这是需要保存在内存中的相当大的数据量。如果它来自数据库,那么使用数据库函数可能会更容易(并且上面的大多数单词仍然符合)。

还是太慢了?为您的数据集建立索引。如果您预先知道哪些元素包含“A”,则所需的搜索数量可能会显着下降。并且您已经获得了第一次搜索的结果

当您使用锚定搜索时,处理排序数组可以提供更好的性能特征。只需使用二分搜索找到搜索词的第一个和最后一个元素并使用该范围即可。也许甚至不需要复制到新数组中。这种方法会预先增加一些工作量(可能在用户开始打字之前)。如果您的搜索数据位于较大的对象中,则可以使用某种索引表。