滞后滚动tableview与动态stackview

问题描述

我正在使用一个复杂的TableViewCell,该表内部有一个CollectionView和一个StackView。此单元格可以在StackView中具有多个子视图(大约100个视图),具体取决于选择了多少ColectionViewCell。问题是当在表格上滚动时,当下一个单元格出队时,它会滞后。我认为主要原因是因为它要从堆栈中删除所有子视图,然后再次添加它们。

class MainViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {

    func numberOfSections(in tableView: UITableView) -> Int {
        return presenter?.numberOfSections ?? 0
    }
    
    func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        return presenter?.numberOfJobs(in: section) ?? 0
    }

    func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: SelectionCell = tableView.dequeueReusableCell(for: indexPath)
        if let activity = presenter?.activity(at: indexPath),let name = presenter?.name(at: indexPath) {
            cell.configure(activity: activity,value: presenter?.rate(at: indexPath),name: name,infos: presenter?.InfosDesc(at: indexPath) ?? [],selectedRowIndices: presenter?.selectedRowIndices(at: indexPath) ?? [],offset: offsetsForIndexPaths[indexPath],delegate: self,row: indexPath.row)
        }

        cell.didSelectRowHandler = { [weak self] rowIndex in
            self?.presenter?.didSelectRow(activityIndexPath: indexPath,rowIndex: rowIndex)

            if let indexPathsToReload = tableView.indexPathsForVisibleRows {
                tableView.reloadRows(at: indexPathsToReload,animated: false)
            }
        }
        
        cell.didSelectAllHandler = { [weak self] in
                self?.presenter?.didSelectAllRows(activityIndexPath: indexPath)
                    if let indexPathsToReload = tableView.indexPathsForVisibleRows {
                        tableView.reloadRows(at: indexPathsToReload,animated: false)
                    }
        }
        
        cell.diddeselectAllHandler = { [weak self] in
                self?.presenter?.diddeselectAllRows(activityIndexPath: indexPath)
                    if let indexPathsToReload = tableView.indexPathsForVisibleRows {
                        tableView.reloadRows(at: indexPathsToReload,animated: false)
                    }
        }

        cell.diddeselectRowHandler = { [weak self] rowIndex in
            self?.presenter?.diddeselectRow(activityIndexPath: indexPath,animated: false)
            }
        }

        cell.didInputNumberForRow = { [weak self] number,rowNumber in
            self?.presenter?.didInputNumber(activityIndexPath: indexPath,value: number,for: rowNumber)
        }

        cell.didScrollHandler = { [weak self] offset in
            self?.offsetsForIndexPaths[indexPath] = offset
        }

        cell.didChangeValue = { [weak self] newValue in
            self?.presenter?.didChangeValue(newValue,activityIndexPath: indexPath)
        }

        return cell
    }
}
class SelectionCell: UITableViewCell {

    var didSelectRowHandler: ((Int) -> Void)?
    var didChangeValue: ((Double) -> Void)?
    var didInputNumberForRow: ((Int,Int) -> Void)?
    var diddeselectRowHandler: ((Int) -> Void)?
    var didScrollHandler: ((CGPoint) -> Void)?
    
    var didSelectAllHandler: (() -> Void)?
    var diddeselectAllHandler: (() -> Void)?

... other properties ... 

    private lazy var inputField: CustomInputField = { ... }
    private lazy var numberFields = UIStackView.vertical(spacing: 10)

    private lazy var collectionView: UICollectionView = { … }


    override func prepareForReuse() {
        super.prepareForReuse()

        imageView.image = nil
        numberFields.subviews.forEach { $0.removeFromSuperview() }
        activityLabel.attributedText = nil
        otherLabel.isHidden = true
        inputField.value = nil
    }

    func configure<Delegate: UICollectionViewDataSource>( activity: Activity,value: Double?,name: String,infos: [(Info,NSAttributedString)],selectedRowIndices: [Int],offset: CGPoint?,delegate: Delegate,row: Int) {
        
        if activity.type.typeName?.caseInsensitiveCompare(activity.type.name) != .orderedSame {
            activityTypeLabel.attributedText = NSAttributedString(string: activity.type.name,attributes: .treeNumberInfoText)
        }

        InputField.value = value
        nameLabel.attributedText = NSAttributedString(string: name,attributes: .treeNumberInfoText)

        let image = GraphicHelper.createImage(withInitials: name.nameInitials,backgroundColor: .random(seed: name,maxBrightness: 0.7),attributes: .initials,diameter: 50)
        userImageView.image = image

    { ... more cell configuration ... }

        infos.forEach { info,desc in
            let infoInputField = InfoInputDescriptionView(info: info,description: desc,delegate: self)

            infoInputField.addArrangedSubview(infoInputField)
        }

        collectionView.dataSource = delegate
        collectionView.tag = row

        collectionView.reloadData()
        dispatchQueue.main.async {
            self.collectionView.performBatchUpdates(nil) { _ in
                selectedRowIndices.forEach { rowIndex in
                    let path = IndexPath(row: rowIndex,section: 0)
                    if self.collectionView.isIndexPathValid(path) {
                        self.collectionView.selectItem(at: path,animated: false,scrollPosition: .centeredHorizontally)
                    }
                }

                if let offset = offset {
                    self.collectionView.setContentOffset(offset,animated: false)
                }
            }
        }
        
        didSelectAll =  selectedRowIndices.count == collectionView.numberOfItems(inSection: 0)
    }


extension SelectionCell: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView,didSelectItemAt indexPath: IndexPath) {
        didSelectRowHandler?(indexPath.row)
    }

    func collectionView(_ collectionView: UICollectionView,diddeselectItemAt indexPath: IndexPath) {
        diddeselectRowHandler?(indexPath.row)
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        didScrollHandler?(scrollView.contentOffset)
    }
}

我尝试重用StackCells而不是全部删除它们,但是每次都要重新配置StackViews很复杂(无法解决滞后问题),同时下一个TableCell可能具有或未选择值,因此堆栈可能是空的。此时,我正在考虑将TableView替换为StackView,还有其他建议吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)