Я был удивлен, узнав, сколько было препятствий для реализации UICollectionView в UITableViewCell. Поэтому этот туториал здесь, надеюсь он сэкономит вам много времени.

Примечание: это туториал не для начинающих. Предполагается, что вы знаете о tableViews и создании пользовательских ячеек с файлами xib.

Также я не описываю ничего, про визульную составляющую.

1) Добавьте UICollectionView к вашей TableViewCell Xib

  1. Перетащите UICollectionView в ваш TableViewCell Xib
  2. Добавить констрейны
  3. И узнайте, что вы не можете добавить CollectionViewCells в свой недавно добавленный UICollectionView :)

Оказывается, вам нужен отдельный файл для размещения любых ячеек представления коллекции, которые вы хотите отобразить. (Когда ваш UICollectionView находится в Xib-файле)

2) Добавьте файл UICollectionViewCell и Xib в ваш проект

image

Вы можете делать все, что захотите, в своем ячейки коллекции Collection View Cell Xib (добавить label, image и тд.), для целей этого туториала мы это здесь не трогаем.

Убедитесь, что вы даете своей ячейке resuableIdentifier.

image

3) Убедитесь в соответствие вашего класса TableViewCell UICollectionView Data Source и Delegate протоколы.

Шаг 1: Вернитесь к вашему Xib-файлу tableViewCells.

image

Шаг 2: Перетащите из вашего collectionView в ‘File’s Owner’ и выберите dataSource и затем delegate.

image

Шаг 3: Перетащите из вашего collectionView в ваш класс TableViewCell и создайте IBOutlet

image

Шаг 4: Убедитесь в соответствие вашего класса TableViewCell UICollectionView Data Source и Delegate протоколы.

class TableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
    @IBOutlet weak var collectionView: UICollectionView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        self.collectionView.dataSource = self
        self.collectionView.delegate = self
        self.collectionView.register(UINib.init(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "collectionViewID")
        
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 15
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewID", for: indexPath as IndexPath) as! CollectionViewCell
        
        
        return cell
    }
}

Пояснение к коду:

  1. Добавьте UICollectionViewDelegate и UICollectionViewDataSource к описанию класса
  2. Сделайте datasource collectionView и delegate = self в awakeFromXib
  3. Добавьте функцию numberOfItemsInSection
  4. Добавьте функцию cellForItemAt
  5. Создайте ячейку с вашим reuseIdentifier как свою пользовательскую ячейку.

Действия по устранению неполадок:

  1. Мои идентификаторы назначены и корректны?
  2. Перетащил ли я из своего collectionView в Files Owner в вашем Xib-файле?

Если есть вопросы, пишите в комментариях.

Если это вам помогло или поможет в будещем поставьте лайк.

Надеюсь кому то это сэкономит очень много времени.

Комментарии (5)


  1. alexwillrock
    25.04.2019 13:58

    Зачем?
    когда можно создать вью модель, создать коллекцию с секциями и для секции сделать вертикальную / горизонтальную верстку.


    1. aposnov Автор
      25.04.2019 14:24

      Здесь решалась задача когда есть UITableView, у него есть кастомная UITableViewCell реализованная через xib, и в этот xib уже добавляется UICollectionView.


  1. Rayllienstery
    25.04.2019 14:17

    А зачем нам, простите, ещё один слой абстракции, когда сам CollectionView более, чем самодостаточный.
    Разве что вы планируете делать галерею из стикеров, я не знаю. Тут первый набор, в следующей Cell второй. но тогда вы очень рискуете нарваться на то, что ваше устройство не будет выставлять приоритет так, как вы этого ожидаете.


    1. aposnov Автор
      25.04.2019 14:21

      на ваш вопрос отвечает первый пункт)


  1. juicyfru1t
    25.04.2019 17:06

    Нужно ещё решать проблему с reuse и сохранением offset: хранить где-то contentOffset для конкретной ячейки