我有一个预装了20000条记录的数据库。
基本上有两个实体在其中进行搜索,City Entity
而另一个实体是street Entity
。 City有“名称”属性,Street Entity
也有名称属性,city and street
都在one-to-many relationship
。因为一个城市可以有很多街道。
现在,当用户可以使用“a或b”之类的任何字符进行搜索时,它应该向用户显示相应的城市和/或街道.Eveytime我必须重新加载并重新配置NSFetchedResultsController。
我已经实施了NSPredicate
来过滤掉记录。
let predicate = NSPredicate(format:"(name CONTAINS[c] %@) OR (SELF.streets.name CONTAINS[c] %@)",text,text)
predicateArray.append(predicate)
这个谓词用于过滤记录。我也使用MagicalRecord作为coreData的包装器。搜索过去就像我在寻找每个角色一样。
非常感谢任何帮助。
答案 0 :(得分:1)
我试着在内存20000行中进行过滤。它速度超快!完全没有滞后。你似乎不止一次去持久性商店,这就是我的建议:
NSFetchedResultController
(在此之前尝试第三点可行)NSFetchRequest
:其中一个将为您提供城市,另一个将为您提供街道。因此,您将获得一系列城市和一系列街道。
这种方法可以帮助您避免获取非常低效的关系city.streets
。如果你可以将两者组合并映射到单个字符串数组,那就更好了。request.returnsObjectsAsFaults = false
。否则,您将继续访问数据库以获取city.name或street.name。搜索文本字段更改时:
tableView
编辑:测试示例 我测试了下面的代码
iPhone 6:第一个字符在100ms-170ms之间。然后它变得更快。 (2x)我觉得有任何滞后。
iPad mini 2:第一个字符在300ms到350ms之间。然后它变得更快。 (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]
}
}
答案 1 :(得分:0)
由于您正在使用如此庞大的数据库,因此将数据库编入索引可能是一个好主意。
这样可以提高搜索速度,因为您只需查看匹配的索引,而不必每次都查看数据库中的所有20,000条记录。可以把它想象成在书的索引中查找某些内容,而不必阅读每一页以找到您正在寻找的内容。
iOS中的核心数据内置了索引。尝试在要编制索引的属性上启用它,看看是否有助于加快搜索时间。
答案 2 :(得分:0)
您可以尝试使用以下选项来提高提取速度。
在您的情况下,以下内容可能有助于检索更快的结果,
如果您需要
,可以使用以下内容详细参考:CoreData