【问题标题】:Realm/iOS: Bumpy scrolling performance for UICollectionViewRealm/iOS:UICollectionView 的颠簸滚动性能
【发布时间】:2016-10-01 05:35:15
【问题描述】:

我第一次使用 Realm 作为 coredata 的替代品。

  1. 可悲的是,当我尝试 Realm 时,collectionView 出现了这个颠簸的滚动问题(这不是太糟糕,但很明显)。没有数据下载阻塞主线程,我使用本地存储的图像。

  2. 另一个问题是当我push到另一个collectionVC时,如果当前VC将数据传递给另一个,segue也很颠簸。

我猜这是因为我在领域模型中编写此 children 属性的方式。但我不知道计算这个数组值数组的好方法是什么(将不同类型的列表合并为一个)

提前非常感谢您!

这是我用于 collectionView 的主要模型

class STInstitution: STHierarchy, STContainer {

    let boxes = List<STBox>()
    let collections = List<STCollection>()
    let volumes = List<STVolume>()

    override dynamic var _type: ReamlEnum {
        return ReamlEnum(value: ["rawValue": STHierarchyType.institution.rawValue])
    }

    var children: [[AnyObject]] {

        var result = [[AnyObject]]()
        var tempArr = [AnyObject]()

        boxes.forEach{ tempArr.append($0) }
        result.append(tempArr)
        tempArr.removeAll()

        collections.forEach{ tempArr.append($0) }
        result.append(tempArr)
        tempArr.removeAll()

        volumes.forEach{ tempArr.append($0) }
        result.append(tempArr)

        return result
    }

    var hierarchyProperties: [String] {
        return ["boxes", "collections", "volumes"]
    }
}

这是我实现 UICollectionViewController 的方式:

override func viewDidLoad() {

    super.viewDidLoad()

    self.collectionView?.alwaysBounceVertical = true

    dataSource = STRealmDB.query(fromRealm: realm, ofType: STInstitution.self, query: "ownerId = '\(STUser.currentUserId)'")

}

// MARK: - 数据源:

override func numberOfSections(in collectionView: UICollectionView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of items
    guard let dataSource = dataSource else { return 0 }
    return dataSource.count
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! STArchiveCollectionViewCell

    guard let dataSource = dataSource,
        dataSource.count > indexPath.row else {
            return cell
    }

    let item = dataSource[indexPath.row]
    DispatchQueue.main.async {
        cell.configureUI(withHierarchy: item)
    }

    return cell
}

// MARK: - 打开项目

func pushToDetailView(dataSource: [[AnyObject]], titles: [String]) {
    guard let vc = storyboard?.instantiateViewController(withIdentifier: STStoryboardIds.archiveDetailVC.rawValue) as? STArchiveDetailVC
    else { return }
    vc.dataSource = dataSource
    vc.sectionTitles = titles
    self.navigationController?.pushViewController(vc, animated: true)
}

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    guard let dataSource = self.dataSource,
        dataSource.count > indexPath.row else {
            return
    }
    let item = dataSource[indexPath.row]
    self.pushToDetailView(dataSource: item.children, titles: item.hierarchyProperties)
}

修改(configureUI上的更多代码):

// configureUI
// data.type is an enum type

func configureUI<T: STHierarchy>(withHierarchy data: T) {
    print("data", kHierarchyCoverImage + "\(data.type)")
    titleLabel.text = data.title
    let image = data.type.toUIImage()
    self.imageView.image = image
}

// toUIImage of enum data.type

func toUIImage() -> UIImage {

    let key = kHierarchyCoverImage + "\(self.rawValue)" as NSString

    if let image = STCache.imageCache.object(forKey: key) {
        return image
    }else{
        print("toUIImage")
        let defaultImage = UIImage(named: "institution")
        let image = UIImage(named: "\(self)") ?? defaultImage!
        STCache.imageCache.setObject(image, forKey: key)
        return image
    }
}

【问题讨论】:

    标签: ios swift uicollectionview realm


    【解决方案1】:

    如果您在滚动时 UI 出现凹凸不平,仅表示您在 collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -&gt; UICollectionViewCell 中执行的操作太繁重。

    Realm 本身的结构使得从对象中读取数据的速度非常快,因此如果您所做的只是用来自领域。

    几个注意事项:

    • 如果您在cellForItem 块方法中调用item.children,因为您在每个Realm 对象中手动循环和分页,这将导致丢帧。如果是这样,最好提前这样做,或者重新设计逻辑以仅在绝对需要时访问这些数组。
    • 您提到要包含图像。即使图像在磁盘上,除非您提前强制解压缩图像,否则 Core Animation 会在主线程上绘制时延迟解压缩图像,这会严重影响滚动性能。请参阅this question 了解更多信息。
    • cellForItemAt 方法调用应该已经在主线程上,因此在DispatchQueue.main.async 闭包中配置您的单元格似乎是不必要的,并且考虑到它不是同步的,可能会因无序运行而导致其他问题。
    • 众所周知,集合视图很难提高性能,因为整行单元格过去是在一次运行循环迭代中创建和配置的。此行为在 iOS 10 中进行了更改,以将单元格创建分散到多个运行循环迭代中。请参阅this WWDC video,了解如何优化您的集合视图代码以利用这一点。

    如果您仍然遇到问题,请发布更多示例代码;最重要的是configureUI的内容。谢谢!

    【讨论】:

    • 感谢您的所有建议!不幸的是,在尝试了 iOS 10 的优化 collectionView 后,我仍然遇到了这个问题。 1、cellForItem中没有调用item.children,只有在用户点击单元格触发segue时才会调用。 2.我已经注释掉了应用图像的代码。转场变得光滑,但是,滚动仍然颠簸 3。有关更多代码详细信息,请参阅我的问题的修改。谢谢!!!
    【解决方案2】:

    原来我关注的是错误的一面。我对 Realm 的缺乏经验让我觉得我在 Realm 上做的一定有问题。然而,真正的罪魁祸首是我忘记定义自定义单元格的阴影路径,重复绘制真的很昂贵。直到我使用时间配置文件检查哪些方法占用的 CPU 最多,我才发现这一点,我应该一开始就这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-10
      • 1970-01-01
      • 1970-01-01
      • 2022-12-11
      • 2014-06-07
      • 2022-11-24
      • 1970-01-01
      相关资源
      最近更新 更多