Доступ к файлу представления из UICollectionViewListCell

У меня вопрос о разделителе списка представлений UICollectionLayoutGuide. Я увидел эту статью и понял, что мне нужно переопределить функцию updateConstraints(), чтобы обновить руководство по макету разделителя. нравится...

      override func updateConstraints() {
  super.updateConstraints()

  separatorLayoutGuide.leadingAnchor.constraint(equalTo: otherView.leadingAnchor, constant: 0.0).isActive = true
}

Я вижу крошечное пространство между ведущим якорем ячейки и ведущим якорем seprateguide, как на изображении ниже, и я хочу это исправить. (как левая часть клетки)

Проблема, однако, в том, что я создал ячейку списка пользовательского представления коллекции, используя эту статью , и не могу изменить separatorLayoutGuide, ведущий к ведущему элементу настраиваемого представления. Я добавил customListCell.separatorLayoutGuide.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true чтобы поместить ведущий элемент separatorLayoutGuide в ведущий элемент customView, и я получаю

      "UILayoutGuide:0x2822d8b60'UICollectionViewListCellSeparatorLayoutGuide'.leading"> and <NSLayoutXAxisAnchor:0x280e9cac0 "ContentView:0x15960db90.leading"> because they have no common ancestor.  Does the constraint or its anchors reference items in different view hierarchies?  That's illegal.'

ошибка. После того, как я провел исследование, я решил, что не добавлял Subview для separatorLayoutGuide, но даже если я добавляю subview в настраиваемый вид, приложение вылетает. Есть ли способ изменить ведущую привязку направляющей разделителя при использовании пользовательского UIView?

      class CustomListCell: UICollectionViewListCell {

    var item: TestItem?
    
    override func updateConfiguration(using state: UICellConfigurationState) {
        
        // Create new configuration object
        var newConfiguration = ContentConfiguration().updated(for: state)
        
            newConfiguration.name = item.name
            newConfiguration.state = item.state

        // Set content configuration
        contentConfiguration = newConfiguration
    }
}


struct ContentConfiguration: UIContentConfiguration, Hashable {
    
    var name: String?
    var state: String?
    
    func makeContentView() -> UIView & UIContentView {
        return ContentView(configuration: self)
    }
    
    func updated(for state: UIConfigurationState) -> Self {
        guard let state = state as? UICellConfigurationState else {
            return self
        }
        
        // Updater self based on the current state
        let updatedConfiguration = self
        if state.isSelected {
            print("is selected")
        } else {
            print("is deselected")
        }
        return updatedConfiguration
    }
}


class ContentView: UIView, UIContentView {

    let contentsView = UIView()
    let customListCell = CustomListCell()

    lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.text = ""
        return label
    }()

    lazy var statusLabel: UILabel = {
        let label = UILabel()
        label.text = ""
        return label
    }()

    lazy var symbolImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()

    init(configuration: ContentConfiguration) {
          // Custom initializer implementation here.
        super.init(frame: .zero)
        setupAllViews()
        apply(configuration: configuration)
    }


    override func updateConstraints() {
        super.updateConstraints()
        customListCell.separatorLayoutGuide.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private var currentConfiguration: ContentConfiguration!
    var configuration: UIContentConfiguration {
        get {
            currentConfiguration
        }
        set {
            guard let newConfiguration = newValue as? ContentConfiguration else {
                return
            }

            apply(configuration: newConfiguration)
        }
    }

    func setupAllViews() {
        // add subviews and add constraints
    }

    func apply(configuration: ContentConfiguration) {

    }
}

2 ответа

В вашем коде у вас есть customListCellпеременная экземпляра, которая не является необходимой. Также не следует добавлять separatorLayoutGuideкак подпредставление в любом месте.

Попробуйте получить доступ к ячейке contentView:

      override func updateConstraints() {
    super.updateConstraints()

    if let customView = cell.contentView as? ContentView {
      separatorLayoutGuide.leadingAnchor.constraint(equalTo: customView.leadingAnchor, constant: 0.0).isActive = true
    }
}

Таким образом, вы можете получить доступ к любому подпредставлению в вашем ContentView.

Другой вопрос: нужно ли создавать новое ограничение каждый раз, когда вызывается? Сохраняются ли ограничения предыдущих вызовов? Согласно документации г. updateConstraints:

Ваша реализация должна быть максимально эффективной. Не отключайте все свои ограничения, а затем повторно активируйте те, которые вам нужны. Вместо этого ваше приложение должно каким-то образом отслеживать ваши ограничения и проверять их при каждом проходе обновления. Меняйте только те элементы, которые необходимо изменить. Во время каждого прохода обновления вы должны убедиться, что у вас есть соответствующие ограничения для текущего состояния приложения.

Поэтому я предлагаю такой подход:

      class ContentView: UIView, UIContentView {
    var separatorConstraint: NSLayoutConstraint?
    func updateForCell(_ cell: CustomListCell) {
        if separatorConstraint == nil {
            separatorConstraint = cell.separatorLayoutGuide.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 30)
        }
        separatorConstraint?.isActive = true
    }
}

class CustomListCell: UICollectionViewListCell {
    ...
    override func updateConstraints() {
        super.updateConstraints()
        (contentView as? AlbumContentView)?.updateForCell(self)
    }
}

путем переопределения updateConstraints в UICollectionViewListCellподкласс

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