我有一个包含 20000 条记录的预加载数据库。
基本上有两个实体在其中完成搜索,City Entity
和另一个是street Entity
。 City有“Name”属性,Street Entity
也有name属性,city和street
都是一对多
关系。因为一个城市可以有很多街道。
现在,当用户可以使用任何字符(如“a 或 b”)进行搜索时,它应该向用户显示相应的城市和/或街道。每次我都必须重新加载和重新配置 NSFetchedResultsController。
我已经实现了一个 NSPredicate
来过滤记录。
let predicate = NSPredicate(format:"(name CONTAINS[c] %@) OR (SELF.streets.name CONTAINS[c] %@)",text,text)
predicateArray.append(predicate)
这个谓词用于过滤记录。我还在使用 MagicalRecord 对 coreData 的包装。搜索过去非常频繁,因为我正在搜索每个字符。
如有任何帮助,我们将不胜感激。
最佳答案
我尝试在内存中过滤 20000 行。速度 super 快!一点都不滞后。看来您将多次访问持久存储,这就是我的建议:
- 停止使用
NSFetchedResultController
(在这样做之前尝试第三点它可以工作) - 创建两个
NSFetchRequest
:其中一个将为您提供城市,另一个将为您提供街道。所以你会得到一系列的城市和一系列的街道。 这种方法将帮助您避免获取效率非常低的关系city.streets
。如果您可以将两者组合并映射到单个字符串数组,那就更好了。 - 非常重要:设置
request.returnsObjectsAsFaults = false
。否则,您将继续前往数据库获取 city.name 或 street.name。
当搜索文本字段更改时:
- 首先过滤城市,然后过滤街道。
- 重新加载
tableView
编辑:测试示例 我测试了下面的代码
iPhone 6:第一个字符在 100 毫秒到 170 毫秒之间。然后它变得更快。 (2x) 我没有感觉到任何延迟。
iPad mini 2:第一个字符在 300 毫秒到 350 毫秒之间。然后它变得更快。 (2x) 有一些滞后。
class ViewController: UIViewController, UISearchBarDelegate, UITableViewDataSource{ @IBOutlet weak var tableView: UITableView! @IBOutlet weak var searchBar: UISearchBar! var streets = [Street]() var cities = [City]() var filteredStreets: [Street] = [] var filteredCities: [City] = [] override func viewDidLoad() { super.viewDidLoad() cities = findAllCities() streets = findAllStreets() filteredCities = cities filteredStreets = streets } func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { filterItemsWithCurrentSearchText(searchText) } func filterItemsWithCurrentSearchText(text: String){ if text.isEmpty { filteredStreets = streets filteredCities = cities } else { NSLog("1") filteredStreets = streets.filter{ $0.name.rangeOfString(text, options: .CaseInsensitiveSearch) != nil } NSLog("2") filteredCities = cities.filter{ $0.name.rangeOfString(text, options: .CaseInsensitiveSearch) != nil } NSLog("3") } tableView.reloadData() NSLog("4") } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return filteredStreets.count + filteredCities.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell")! if indexPath.row < filteredCities.count{ cell.textLabel!.text = "City:" + filteredCities[indexPath.row].name }else{ cell.textLabel!.text = "Street:" + filteredStreets[indexPath.row-filteredCities.count].name } return cell } func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } func findAllCities() -> [City]{ let request = City.MR_createFetchRequest() request.returnsObjectsAsFaults = false return City.MR_executeFetchRequest(request) as! [City] } func findAllStreets() -> [Street]{ let request = Street.MR_createFetchRequest() request.returnsObjectsAsFaults = false return Street.MR_executeFetchRequest(request) as! [Street] } }
关于ios - 使用 NSFetchedResultsController 搜索每个字符 CoreData 的速度非常慢,有大量记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40418506/