UIConfigurationStateCustomKey with UIContentView.

I'm trying to implement additional UICollectionViewCell's state using UIConfigurationStateCustomKey.

I've already read this post regarding practices for managing custom properties with cells configurations

Seems like I can implement custom state for a UICollectionView's cell.

Here is my implementation of additional state

protocol CustomTypesAccessable: AnyObject {
  var isMoving: Bool { get set }
}

extension UIConfigurationStateCustomKey {
  static let isMoving = UIConfigurationStateCustomKey("com.myApp.cell.isMoving")
}

extension UICellConfigurationState {
  var isMoving: Bool {
    get { self[.isMoving] as? Bool ?? false }
    set { self[.isMoving] = newValue }
  }
}

extension BaseBlockView: CustomTypesAccessable {
  var isMoving: Bool {
    get {
      currentConfiguration.currentConfigurationState?.isMoving ?? false
    }
    set {
      currentConfiguration.currentConfigurationState?.isMoving = newValue
    }
  }
}

My BaseBlockView class:

class BaseBlockView<Configuration: BlockConfigurationProtocol>: UIView, UIContentView {
  var configuration: UIContentConfiguration {
    get { currentConfiguration }
    set {
      guard let newConfiguration = newValue as? Configuration,
         currentConfiguration != newConfiguration else { return }

      currentConfiguration = newConfiguration
    }
  }
  var currentConfiguration: Configuration {
    didSet {
      guard didSetupSubviews else { return }
      update(with: currentConfiguration)
    }
  }

I want to update this state from my view controller in the same way CollectionView can make cell selected

- (void)selectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition;

So I'm trying to change isMoving value this way:

  let cell = cellForItem(at: indexPath)
    let contentView = cell?.contentView as? CustomTypesAccessable

    contentView?.isMoving = isMoving

Everything works fine in that case, but after reusing cell UICellConfigurationState's isMoving property changes back to false. Is it a UIKit bug?

Accepted Reply

When adding a custom state to UICellConfigurationState, the custom state needs to be populated by overriding the configurationState property getter on the cell subclass, which means you are responsible for providing your own storage of any custom states on the cell. You can see a complete example of this in the documentation.

Your code above shows that you are trying to add the custom state to the cell's contentView (BaseBlockView) instead of the cell itself, which won't work. The UICellConfigurationState is a property of the cell, not the contentView, and you can't modify the true configuration state of the cell (e.g. to add a custom state) without overriding the configurationState getter.

Replies

When adding a custom state to UICellConfigurationState, the custom state needs to be populated by overriding the configurationState property getter on the cell subclass, which means you are responsible for providing your own storage of any custom states on the cell. You can see a complete example of this in the documentation.

Your code above shows that you are trying to add the custom state to the cell's contentView (BaseBlockView) instead of the cell itself, which won't work. The UICellConfigurationState is a property of the cell, not the contentView, and you can't modify the true configuration state of the cell (e.g. to add a custom state) without overriding the configurationState getter.

Thanks for the answer!

I am using UICollectionView.CellRegistration<UICollectionViewListCell, Item>. So seems like I need to inherit from UICollectionViewListCell with code from documentation.