Создание экземпляра UICellAccessory.customView и его использование в нескольких аксессуарах listCell приводит к зависанию

Я хотел сделать такой интерфейс.

Компонент изображения шеврона вниз в правой части ячейки — это тот, который я настроил. С этого момента я буду называть это.

Чтобы создать этот пользовательский интерфейс, я настроилdataSourceс и следующим образом.

      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)
    }
}

И я понял, что существует дублирующийся код для создания экземпляра в и, поэтому решил сделать этот аксессуар одной переменной и использовать его совместно.

      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]
}

Но приведенный выше код вызвал зависание.

При взгляде на инструмент «Инструменты»UICellAccessoryManager_updateAccessories:prevailingAccessories:withLayout:edge:функция занимала слишком большой вес.

Загрузка процессора составила 100%, а использование памяти также продолжало расти.

Однако если я создаю и использую аксессуар через функцию, возвращающую , в этой ситуации ошибки не возникнет.

      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()]
}

Я подумал: «Ну, разве проблема была в том, чтобы использовать один и тот же экземпляр?». И присваивается переменным вredCellRegistrationиblueCellRegistrationв отдельности. (ПосколькуUICellAccessoryявляется структурой, если я назначу ее переменной, экземпляр будет скопирован.)

      
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
}()

Есть ли что-нибудь, что поможет понять эту ситуацию с ошибкой?

1 ответ

является структурой, ноподкласс, который он содержит при создании пользовательского аксессуара, является классом. При копировании структуры будет использоваться тот же экземпляр представления; новое представление не будет создано. Вы не можете использовать одно и то же пользовательское представление (в вашем примере) между ячейками.

Вы уже нашли правильное решение: вам нужно создать новый экземплярдля каждой отдельной строки, если вы используете собственное представление. Ваш исходный код работал, но чтобы избежать дублирования, вы можете использовать фабричный метод для создания нового аксессуара ячейки. Это было другое ваше решение, которое сработало, потому что оно создавало новый экземпляр при каждом вызове.

Другие вопросы по тегам