在我正在开发的应用程序中,我必须从一个相当大的数据库中获取和使用数据(文本和图像),并且当加载 tableview 时,应用程序卡住 2-5 秒。这可能会破坏 UX,因为 UI 感觉响应速度不快。
我认为问题是存在许多图像(不是很重,50x50px
),每个自定义单元格都有一个, 并且大约有 1000+ 行。
我需要知道哪种最佳方式可以避免这种较长的加载时间,或者如何隐藏它。
用户打开 tableview 单击一个按钮,执行 segue,然后我在 viewDidLoad()
中获取数据。正如我发现的那样,viewDidLoad()
方法可以阻止交互,直到它完成。在 viewDidLoad() 中,我调用了一个名为 fetchCard()
的函数。它将 Card
对象放入数组中,其中包含我在单元格中使用的属性(名称、缩略图)。
func fetchCard() {
cards = []
let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: "Card")
let sorter: NSSortDescriptor = NSSortDescriptor(key: sorterParameter , ascending: true)
fetchRequest.predicate = definitivePredicate
fetchRequest.sortDescriptors = [sorter]
fetchRequest.returnsObjectsAsFaults = true
do {
let results = try moc.executeFetchRequest(fetchRequest)
cards = results as! [Card]
} catch {
print("Fetch failed: \(error)")
}
}
有没有办法加载,例如,只加载可见的行,这行得通吗/这样做是个好习惯吗?有没有更好的方法?
P.S.:为了避免基于个人喜好的讨论,“更好”是指在加载速度方面具有最高性能的方式。
编辑:添加了代码示例。
最佳答案
问题是您在 viewDidLoad() 方法中加载了许多数据,并且您没有在后台线程上异步加载它们。当您在 viewDidLoad() 中调用 fetchCard() 时,您会阻止整个屏幕的加载,直到从数据库加载完成。
要在后台线程上加载数据,您必须这样做:
let queue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)
dispatch_async(queue, { () -> Void in
let context: NSManagedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
context.parentContext = moc
let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: "Card")
let sorter: NSSortDescriptor = NSSortDescriptor(key: sorterParameter , ascending: true)
fetchRequest.predicate = definitivePredicate
fetchRequest.sortDescriptors = [sorter]
fetchRequest.returnsObjectsAsFaults = true
do {
let results = try context.executeFetchRequest(fetchRequest)
cards = results as! [Card]
} catch {
print("Fetch failed: \(error)")
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
tableView.reloadData()
})
})
此外,如果从 CoreData 加载速度变慢,您将必须找出原因。将索引添加到您排序/过滤所依据的对象中的变量可能会有所帮助。在 sortDescriptors
中添加 1 个描述符,尝试索引描述符中使用的 sorterParameter
。
如果您有图像存储在 CoreData 数据库中,异步加载它们可能是明智的,同时保持 tableview 的滚动流畅。您可以使用与以前类似的代码,只需将图像加载移动到 GCD block 中并将图像设置到主线程中的 ImageView ('dispatch_async(dispatch_get_main_queue()
...')。
关于ios - 使用大型数据库时,如何避免在 UITableView 中使用自定义单元格加载时间过长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32977869/