ios - 使用大型数据库时,如何避免在 UITableView 中使用自定义单元格加载时间过长

标签 ios swift uitableview

在我正在开发的应用程序中,我必须从一个相当大的数据库中获取和使用数据(文本和图像),并且当加载 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/

相关文章:

swift 如何修复 TableView 的 segue 准备

dictionary - 如何将项目字典添加到另一个字典中

iOS,重写 cellForRowAtIndexPath 以返回自定义单元格

ios - CAKeyframeAnimation 在 UIImageView 中具有不同的动画持续时间值

ios - 如何在 Swift3 iOS 中的视频 AVAsset 上添加淡入和淡出效果

ios - 通过索引从数组中获取对象,即从另一个数组中获取

ios - 应用程序(_ :url:options:) is never called

ios - 如何在 Controller 的 Root View 中获取按钮的框架

ios - Swift:如何将 UITableView 链接到单个 UIDetailView 页面

ios - 从 `TableViewCell` 触发 `ViewWillAppear` 函数