# 1. Solution for iOS 13
In Swift 5.1 and iOS 13, you can use Compositional Layout objects to solve your problem.
The following complete code example shows how to display a multi-line UILabel inside the full width of a UICollectionViewCell :
CollectionViewController.swift
import UIKit class CollectionViewController: UICollectionViewController { let array = [ "Lorem ipsum.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.", "Lorem ipsum dolor sit amet.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam." ] override func viewDidLoad() { super.viewDidLoad() let size = NSCollectionLayoutSize( widthDimension: NSCollectionLayoutDimension.fractionalWidth(1), heightDimension: NSCollectionLayoutDimension.estimated(44) ) let item = NSCollectionLayoutItem(layoutSize: size) let group = NSCollectionLayoutGroup.horizontal(layoutSize: size, subitems: [item]) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5) section.interGroupSpacing = 5 let layout = UICollectionViewCompositionalLayout(section: section) collectionView.collectionViewLayout = layout collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: CollectionViewCell.cellIdentifier) } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return array.count } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionViewCell.cellIdentifier, for: indexPath) as! CollectionViewCell cell.label.text = array[indexPath.row] return cell } }
CollectionViewCell.swift
import UIKit class CollectionViewCell: UICollectionViewCell { static let cellIdentifier = "CellIdentifier" let label = UILabel() override init(frame: CGRect) { super.init(frame: frame) label.numberOfLines = 0 backgroundColor = .orange contentView.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false label.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
# 2. Solution for iOS 12
In Swift 5 and iOS 12, you can subclass UICollectionViewFlowLayout and set its estimatedItemSize property to UICollectionViewFlowLayoutAutomaticSize (this tells the system that you want to deal with automatic resizing of UICollectionViewCell ). Then you have to redefine layoutAttributesForElements(in:) and layoutAttributesForItem(at:) to set the width of the cells. Finally, you will have to override your preferredLayoutAttributesFitting(_:) cell method and calculate their compressed fitting height.
The following complete code shows how to display a multi-line UILabel inside a full-sized UIcollectionViewCell (limited by the safe area of the UICollectionView and the inserts of the UICollectionViewFlowLayout ):
CollectionViewController.swift
import UIKit class CollectionViewController: UICollectionViewController { let items = [ "Lorem ipsum.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.", "Lorem ipsum dolor sit amet.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam." ] let columnLayout = FlowLayout() override func viewDidLoad() { super.viewDidLoad() collectionView.alwaysBounceVertical = true collectionView.collectionViewLayout = columnLayout collectionView.contentInsetAdjustmentBehavior = .always collectionView.register(Cell.self, forCellWithReuseIdentifier: "Cell") } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return items.count } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell cell.label.text = items[indexPath.row] return cell } }
FlowLayout.swift
import UIKit class FlowLayout: UICollectionViewFlowLayout { override init() { super.init() self.minimumInteritemSpacing = 10 self.minimumLineSpacing = 10 self.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) estimatedItemSize = UICollectionViewFlowLayout.automaticSize } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { guard let layoutAttributes = super.layoutAttributesForItem(at: indexPath) else { return nil } guard let collectionView = collectionView else { return nil } layoutAttributes.bounds.size.width = collectionView.safeAreaLayoutGuide.layoutFrame.width - sectionInset.left - sectionInset.right return layoutAttributes } override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { guard let superLayoutAttributes = super.layoutAttributesForElements(in: rect) else { return nil } guard scrollDirection == .vertical else { return superLayoutAttributes } let computedAttributes = superLayoutAttributes.compactMap { layoutAttribute in return layoutAttribute.representedElementCategory == .cell ? layoutAttributesForItem(at: layoutAttribute.indexPath) : layoutAttribute } return computedAttributes } override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } }
Cell.swift
import UIKit class Cell: UICollectionViewCell { let label = UILabel() override init(frame: CGRect) { super.init(frame: frame) label.numberOfLines = 0 backgroundColor = .orange contentView.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false label.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { layoutIfNeeded() let layoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes) layoutAttributes.bounds.size = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .defaultLow) return layoutAttributes } }
Here are some alternative implementations for preferredLayoutAttributesFitting(_:) :
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { layoutIfNeeded() label.preferredMaxLayoutWidth = label.bounds.size.width layoutAttributes.bounds.size.height = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height return layoutAttributes }
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { label.preferredMaxLayoutWidth = layoutAttributes.size.width - contentView.layoutMargins.left - contentView.layoutMargins.left layoutAttributes.bounds.size.height = systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height return layoutAttributes }
Expected Display:
