我想做一个这样的用户界面
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
}()
UICellAccessory
是一个结构体,但是它在创建自定义配件时存储的 UIView
子类是一个类。复制结构时,将使用相同的视图实例;将 not 创建一个新视图。您不能在单元格之间共享同一个自定义视图(在您的示例中为UIImageView
)。
您已经找到了正确的解决方案:如果您使用的是自定义视图,则需要为每个单独的行创建一个新的
UICellAccessory
实例。您的原始代码有效,但为避免重复,您可以使用工厂方法来创建新的电池配件。那是你的另一个解决方案,因为它每次被调用时都会创建一个新实例。