【问题标题】:GCD Returning Incorrect Results in UITableViewGCD 在 UITableView 中返回不正确的结果
【发布时间】:2017-03-31 23:42:28
【问题描述】:

我有一个列表,其中包含大约 8,500 个加载到 UITableView 中的项目,并且应该只有大约 200 个项目,其中 product.isnewitem 为真。对于每个“新”项目,应该加载一个图像(newicon.png),表明它是一个新项目;但是,当我开始向下滚动表格视图时,newicon 会显示在超过 50% 的项目上。所有项目都是通过 Realm 加载的。

新项目的检查在:

if product.isnewitem {
        cell.newIconImageView.image = #imageLiteral(resourceName: "newicon.png")
    }

这里是整个 cellForRowAtIndexPath 方法:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let paths = NSSearchPathForDirectoriesInDomains(documentsDirectory, userDomainMask, true)

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

    let realm = try! Realm()
    let allProducts = realm.objects(Product.self).sorted(byKeyPath: "basedescription")
    let product = allProducts[indexPath.row]

    cell.productDescriptionLabel.text = product.basedescription

    queue.async {
        let realm = try! Realm()

        let allProducts = realm.objects(Product.self).sorted(byKeyPath: "basedescription")
        let product = allProducts[indexPath.row]

        if product.isnewitem {
            cell.newIconImageView.image = #imageLiteral(resourceName: "newicon.png")
        }

        if let dirPath = paths.first {
            let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent("T\(product.itemno.replacingOccurrences(of: "-", with: "")).png")

            if let image = UIImage(contentsOfFile: imageURL.path) {
                cell.productImageView.image = image
            }
            else {
                cell.productImageView.image = #imageLiteral(resourceName: "image-coming-soon.png")
            }
        }


    }



    return cell
}

【问题讨论】:

  • 您不应该在cellForRow(at:) 中发出异步获取请求。单元格被重用,因此在提取完成时,单元格可能已被重用于另一行。如果项目不是新的,还要确保明确清除“新”图像。
  • @Paulw11 我还应该把异步调用放在哪里?我需要使用某种后台线程,以便 UI 不会滞后,并且我需要访问 IndexPath,因为每个产品图像对于每个单元格都是唯一的。应该改为同步调用吗?最后,“清除”“新”图像是什么意思?

标签: ios swift uitableview realm grand-central-dispatch


【解决方案1】:

我不明白你为什么使用这个代码

let realm = try! Realm()
let allProducts = realm.objects(Product.self).sorted(byKeyPath: "basedescription")
let product = allProducts[indexPath.row]

两次在您的cellForRowAtIndexPath 和一次在队列中,我认为您必须将此代码移动到您的viewController viewDidLoadviewWillAppear,然后使用在您的@987654326 上声明的本地数组中的产品@

var allProducts : Results<Product>?

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let realm = try! Realm()
    self.allProducts = realm.objects(Product.self).sorted(byKeyPath: "basedescription")
}

在你的 cellForRowAtIndexPath 中你应该有这样的东西

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

let paths = NSSearchPathForDirectoriesInDomains(documentsDirectory, userDomainMask, true)

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

let product = self.allProducts[indexPath.row]
cell.productDescriptionLabel.text = product.basedescription
if product.isnewitem {
        cell.newIconImageView.image = #imageLiteral(resourceName: "newicon.png")
    }
else {
        cell.newIconImageView.image = nil
    }

    if let dirPath = paths.first {
        let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent("T\(product.itemno.replacingOccurrences(of: "-", with: "")).png")

        if let image = UIImage(contentsOfFile: imageURL.path) {
            cell.productImageView.image = image
        }
        else {
            cell.productImageView.image = #imageLiteral(resourceName: "image-coming-soon.png")
        }
    }

return cell
}

希望对你有帮助

【讨论】:

  • 我在这个方法中有两个 Realm 实例,因为 Realm 要求您在每个线程中都有一个新实例。一个 Realm 实例不能跨多个线程使用。
  • 图像需要在表格视图的后台线程上加载,因为如果在主线程上加载会显着影响 UI。
  • 您可以在单元格内进行图像加载过程,使用 SDWebImage 或任何其他加载图像,但您只需将 url 传递给单元格,您可以尝试我的答案并告诉我是否我错了吗?
  • @bkhosh2 你终于尝试我的答案了吗?
  • 我立即看到你的回答的一个问题是我不能声明var allProducts : [Product] = [] Realm 对象返回一个数组,但 allProducts 的类型是Results&lt;Product&gt;。当我将 allProducts 声明为 var allProducts : Results&lt;Product&gt; = [] 时,出现错误“上下文类型 Results 不能与数组文字一起使用”。我不知道如何声明一个空的 Realm Results 数组。 Realm API 参考说“结果实例不能直接实例化。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 2016-02-06
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
相关资源
最近更新 更多