创建 UICellAccessory.customView 实例并在多个 listCell 附件中使用它会导致挂起

问题描述 投票:0回答:1

我想做一个这样的用户界面

cell右边的人字形向下的组件就是我自定义的

UICellAccessory
。从现在开始,我就叫这个
moreAccessory
.

为了制作这个 UI,我用

dataSource
redCellRegistration
配置了
blueCellRegistration
,如下所示。

let redCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { (cell, indexPath, item) in
    var content = cell.defaultContentConfiguration()
    content.text = "\(item)"
    content.textProperties.color = .red
    cell.contentConfiguration = content
    let image = UIImageView(image: UIImage(systemName: "chevron.down"))
    let configuration = UICellAccessory.CustomViewConfiguration(customView: image,
                                                                placement: .trailing(),
                                                                tintColor: .systemGray)
    let moreAccessory = UICellAccessory.customView(configuration: configuration)
    cell.accessories = [moreAccessory]
}

let blueCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { (cell, indexPath, item) in
    var content = cell.defaultContentConfiguration()
    content.text = "\(item)"
    content.textProperties.color = .blue
    cell.contentConfiguration = content
    let image = UIImageView(image: UIImage(systemName: "chevron.down"))
    let configuration = UICellAccessory.CustomViewConfiguration(customView: image,
                                                                placement: .trailing(),
                                                                tintColor: .systemGray)
    let moreAccessory = UICellAccessory.customView(configuration: configuration)
    cell.accessories = [moreAccessory]
}

dataSource = UICollectionViewDiffableDataSource<Section, Int>(collectionView: collectionView) {
    (collectionView: UICollectionView, indexPath: IndexPath, identifier: Int) -> UICollectionViewCell? in
    
    if indexPath.row.isMultiple(of: 2) {
        return collectionView.dequeueConfiguredReusableCell(using: redCellRegistration, for: indexPath, item: identifier)
    } else {
        return collectionView.dequeueConfiguredReusableCell(using: blueCellRegistration, for: indexPath, item: identifier)
    }
}

而且我发现在

moreAccessory
redCellRegistration
中创建
blueCellRegistration
实例的代码重复,所以决定把这个附件做成一个单一的变量并共同使用它。

let moreAccessory: UICellAccessory = {
    let image = UIImageView(image: UIImage(systemName: "chevron.down"))
    let configuration = UICellAccessory.CustomViewConfiguration(customView: image,
                                                                placement: .trailing(),
                                                                tintColor: .systemGray)
    let accessory = UICellAccessory.customView(configuration: configuration)
    return accessory
}()


let redCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { (cell, indexPath, item) in
    var content = cell.defaultContentConfiguration()
    content.text = "\(item)"
    content.textProperties.color = .red
    cell.contentConfiguration = content
    cell.accessories = [moreAccessory]
}

let blueCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { (cell, indexPath, item) in
    var content = cell.defaultContentConfiguration()
    content.text = "\(item)"
    content.textProperties.color = .blue
    cell.contentConfiguration = content
    cell.accessories = [moreAccessory]
}

但是上面的代码导致挂起。

看 Instruments 工具时,

UICellAccessoryManager_updateAccessories:prevailingAccessories:withLayout:edge:
功能占了太多权重。

cpu使用率100%,内存使用率也在持续上升

但是,如果我通过返回

moreAccessory
的函数创建和使用配件,在这种情况下没有错误。

func moreAccessory() -> UICellAccessory {
    let image = UIImageView(image: UIImage(systemName: "chevron.down"))
    let configuration = UICellAccessory.CustomViewConfiguration(customView: image,
                                                                placement: .trailing(),
                                                                tintColor: .systemGray)
    let accessory = UICellAccessory.customView(configuration: configuration)
    return accessory
}

let redCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { (cell, indexPath, item) in
    var content = cell.defaultContentConfiguration()
    content.text = "\(item)"
    content.textProperties.color = .red
    cell.contentConfiguration = content
    cell.accessories = [moreAccessory()]
}

let blueCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { (cell, indexPath, item) in
    var content = cell.defaultContentConfiguration()
    content.text = "\(item)"
    content.textProperties.color = .blue
    cell.contentConfiguration = content
    cell.accessories = [moreAccessory()]
}

我想,“好吧,使用同一个实例有问题吗?”。并将

moreAccessory
分别赋值给
redCellRegistration
blueCellRegistration
中的变量。 (因为
UICellAccessory
是struct,如果我把它赋给一个变量,实例就会被复制。)


let moreAccessory: UICellAccessory = {
    let image = UIImageView(image: UIImage(systemName: "chevron.down"))
    let configuration = UICellAccessory.CustomViewConfiguration(customView: image,
                                                                placement: .trailing(),
                                                                tintColor: .systemGray)
    let accessory = UICellAccessory.customView(configuration: configuration)
    return accessory
}()

let redCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { (cell, indexPath, item) in
    var content = cell.defaultContentConfiguration()
    content.text = "\(item)"
    content.textProperties.color = .red
    cell.contentConfiguration = content
    let redCellAccessory = moreAccessory
    cell.accessories = [redCellAccessory]
}

let blueCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { (cell, indexPath, item) in
    var content = cell.defaultContentConfiguration()
    content.text = "\(item)"
    content.textProperties.color = .blue
    cell.contentConfiguration = content
    let blueCellAccessory = moreAccessory
    cell.accessories = [blueCellAccessory]
}

不过,这时候也出错了

如果我将

moreAccessory
作为预定义的附件,例如
disclosureIndicator
,而不是
customView
,则没有错误。

let moreAccessory: UICellAccessory = {
    let accessory = UICellAccessory.disclosureIndicator()
    return accessory
}()

有什么可以了解这种错误情况的线索吗?

ios swift uicollectionview accessory uicollectionviewlistcell
1个回答
1
投票

UICellAccessory
是一个结构体,但是它在创建自定义配件时存储的
UIView
子类是一个类。复制结构时,将使用相同的视图实例;将 not 创建一个新视图。您不能在单元格之间共享同一个自定义视图(在您的示例中为
UIImageView
)。

您已经找到了正确的解决方案:如果您使用的是自定义视图,则需要为每个单独的行创建一个新的

UICellAccessory
实例。您的原始代码有效,但为避免重复,您可以使用工厂方法来创建新的电池配件。那是你的另一个解决方案,因为它每次被调用时都会创建一个新实例。

© www.soinside.com 2019 - 2024. All rights reserved.