【问题标题】:UITableView Performance with Realm Objects in cellForRowAt indexPathUITableView 性能与 cellForRowAt indexPath 中的领域对象
【发布时间】:2017-04-06 18:31:33
【问题描述】:

我的 tableView 中有许多不同的类别部分是从名为 allProducts 的变量加载的,该变量包含我所有的 Realm 对象(Results<Product> 类型)。

然而,自从我介绍这段代码以来,每个部分都加载了正确的产品:

switch productViewSegmentedControl!.selectedSegmentIndex {

    case 0:
        allProductsInSection = allProducts.filter("itemgroup = %@", allProductSections[indexPath.section])
    case 1:
        allProductsInSection = allProducts.filter("itembrand = %@", allProductSections[indexPath.section])
    case 2:
        allProductsInSection = allProducts.filter("itemtype = %@", allProductSections[indexPath.section])
    default:
        allProductsInSection = allProducts.filter("itemgroup = %@", allProductSections[indexPath.section])
    }

在我的 cellForRowAt indexPath 方法中,当滚动到 tableView 有很多项目的部分时,UI 会滞后。

tableView 中的每个单元格都包含let product = allProductsInSection![indexPath.row]product 常量保存了我的 Product 模型类中每个项目的属性。

我可以做些什么来提高 UI 的性能?

附:每个单元格都已被重复使用:

let cell = tableView.dequeueReusableCell(withIdentifier: "ProductCell") as? OrderFormViewCell
            ?? UITableViewCell(style: .subtitle, reuseIdentifier: "ProductCell") as! OrderFormViewCell

【问题讨论】:

    标签: ios swift uitableview realm


    【解决方案1】:

    拥有您在tableView(_:cellForRowAt:) 方法中描述的switch 语句意味着您强制Realm 在每次将要显示单元格时重新过滤产品。从您共享的代码看来,您有一个分段控件来控制要显示的产品。在准备每个单元格时,不要检查分段控件的选择,而应该对其选择变化做出反应,并将您的产品过滤到tableView(_:cellForRowAt:) 可以使用的实例变量中。这将允许 Realm 仅在条件发生更改时过滤产品,而不是每次将要显示单元格时。

    由于您需要在表格视图的每个部分中使用不同的值进行过滤,因此您需要为表格视图的每个部分准备一个Results。在分段控件的选择更改时调用的方法中:

    var productsPerSection = []
    for section in 0..numberOfSections {
        let productsInSection: Results<Product>
        switch productViewSegmentedControl!.selectedSegmentIndex {
            case 0:
                productsInSection = allProducts.filter("itemgroup = %@", allProductSections[section])
            case 1:
                productsInSection = allProducts.filter("itembrand = %@", allProductSections[section])
            case 2:
                productsInSection = allProducts.filter("itemtype = %@", allProductSections[section])
            default:
                productsInSection = allProducts.filter("itemgroup = %@", allProductSections[section])
        }
        productsPerSection.append(productsInSection)
    }
    
    self.productsPerSection = productsPerSection
    

    然后在您的tableView(_:cellForRowAt:) 方法中,使用self.productsInSection[indexPath.section] 而不是过滤来创建allProductsInSection

    注意:代码是未经测试的草图,希望能传达有关该方法的一般想法,但可能无法编译。

    【讨论】:

    • 如何在cellForRow 方法之外更改结果,同时仍然可以访问indexPath.section?你能给我看一个代码示例吗?
    • 我错过了它在过滤器中的使用,因为它在您的代码 sn-p 中不可见,除非向右滚动。哎呀。您可以通过为分段控件的给定选定段使用适当的谓词预先填充由indexPath.section 索引的Results 数组来适应这一点。这意味着您只需为每个部分而不是为您显示的每个单元格过滤一次产品。
    • 我不确定我是否完全理解您要我做什么。我以为我已经在我的谓词中使用 indexPath.section 填充了结果。在cellForRow 方法内完成的任何事情都将针对每个单元格完成。我尝试将 switch 语句放在 numberOfRowsInSection 方法中,它只返回应该在最后一部分中的所有产品。
    • 这个想法是将工作从tableView(_:cellForRowAt:) 中提取出来并响应分段控件的选择更改,因为这种情况很少发生。我在回答中扩展了这种方法。
    【解决方案2】:

    您必须检查是否正确地将单元格出列。此外,如果您在单元格中有图像,那么清理出队的单元格会很好,有一个名为准备重用的函数正确清理您的单元格

    【讨论】:

    • 每个单元格都有一个常量let cell = tableView.dequeueReusableCell(withIdentifier: "ProductCell"),您能告诉我如何实现prepareForReuse() 方法吗?
    • 我可以看到您在该类中有一个自定义单元格类调用 prepareForResue 函数,然后尝试删除您在例如 imageView.image = nil 中的任何重物
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    相关资源
    最近更新 更多