title: Why does UICollectionViewFlowLayout get called multiple times when initializing a class with a UICollectionView, and why not draw correctly?
body: <p>I am trying to develop a UICollectionViewFlowLayout subclass that lays out items like a UITableView. The items use auto layout, and I also support supplementary header views.</p>
  
  <pre><code>open override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -&gt; UICollectionViewLayoutAttributes? {
      guard let attributes = super.layoutAttributesForSupplementaryView(ofKind: elementKind, at: indexPath) else { return nil }
      print("Section Attributes: \(attributes)")
      return attributes
  }
  
  override open func layoutAttributesForItem(at indexPath: IndexPath) -&gt; UICollectionViewLayoutAttributes? {
      let attributes = super.layoutAttributesForItem(at: indexPath)
      if let attributes = attributes {
          guard let collectionView = collectionView else { return attributes }
          attributes.bounds.size.width = collectionView.bounds.width - sectionInset.left - sectionInset.right
      }
      return attributes
  }
  
  override open func layoutAttributesForElements(in rect: CGRect) -&gt; [UICollectionViewLayoutAttributes]?
  {
      print("\nlayoutAttributesForElements: \(rect)")
  
      let allAttributes = super.layoutAttributesForElements(in: rect)
      return allAttributes?.flatMap { attributes in
          switch attributes.representedElementCategory {
          case .cell:
              print("\ncell: \(attributes.indexPath)");
              print("cell_old Attributes: \(attributes)")
              let a = layoutAttributesForItem(at: attributes.indexPath)
              print("cell_new Attributes: \(a)")
              return a
          case .supplementaryView:
              print("\nsupp: \(attributes.indexPath)");
              print("supp_old Attributes: \(attributes)")
              let a = layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindSectionHeader, at: attributes.indexPath)
              print("supp_new Attributes: \(a)")
              return a
          default: return attributes
          }
      }
  }
  </code></pre>
  
  <p>Additionally, my UICollectionViewCell subclass overrides preferredLayoutAttributesFitting:</p>
  
  <pre><code>override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -&gt; UICollectionViewLayoutAttributes
  {
      layoutAttributes.bounds.size.height = systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
      return layoutAttributes
  }
  </code></pre>
  
  <p>This...sort of works. The items are laid out correctly, but section header views draw at the wrong y coordinates. I can hack it by calling <code>collectionView.reloadData()</code> in the view's controller, but this obviously requires everything to be loaded twice, which is wrong.</p>
  
  <p>Debug output shows that layoutAttributesForElements gets called three times before I call <code>reloadData()</code>:</p>
  
  <pre><code>layoutAttributesForElements: (0.0, 0.0, 375.0, 667.0)
  
  cell: [0, 0]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fa100&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); frame = (6 56; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000001fd000&gt; index path: (&lt;NSIndexPath: 0x60000023de40&gt; {length = 2, path = 0 - 0}); frame = (-150.5 56; 363 50); )
  
  cell: [0, 1]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fac00&gt; index path: (&lt;NSIndexPath: 0xc000000000200016&gt; {length = 2, path = 0 - 1}); frame = (68.5 56; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000001fb200&gt; index path: (&lt;NSIndexPath: 0x60000023de20&gt; {length = 2, path = 0 - 1}); frame = (-88 56; 363 50); )
  
  cell: [0, 2]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fa400&gt; index path: (&lt;NSIndexPath: 0xc000000000400016&gt; {length = 2, path = 0 - 2}); frame = (131 56; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000001fd900&gt; index path: (&lt;NSIndexPath: 0x60000023dde0&gt; {length = 2, path = 0 - 2}); frame = (-25.5 56; 363 50); )
  
  cell: [1, 0]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fa900&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); frame = (6 178; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000001fd800&gt; index path: (&lt;NSIndexPath: 0x60000023de00&gt; {length = 2, path = 1 - 0}); frame = (-150.5 178; 363 50); )
  
  cell: [1, 1]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001faf00&gt; index path: (&lt;NSIndexPath: 0xc000000000200116&gt; {length = 2, path = 1 - 1}); frame = (68.5 178; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000001fdb00&gt; index path: (&lt;NSIndexPath: 0x60000023dcc0&gt; {length = 2, path = 1 - 1}); frame = (-88 178; 363 50); )
  
  cell: [1, 2]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fb600&gt; index path: (&lt;NSIndexPath: 0xc000000000400116&gt; {length = 2, path = 1 - 2}); frame = (131 178; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000001fda00&gt; index path: (&lt;NSIndexPath: 0x600000026760&gt; {length = 2, path = 1 - 2}); frame = (-25.5 178; 363 50); )
  
  supp: [0, 0]
  supp_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fb700&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 40); zIndex = 10; 
  Section Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000001fe100&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 40); zIndex = 10; 
  supp_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000001fe100&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 40); zIndex = 10; )
  
  supp: [1, 0]
  supp_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fb800&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 122; 375 40); zIndex = 10; 
  Section Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fb900&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 122; 375 40); zIndex = 10; 
  supp_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6180001fb900&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 122; 375 40); zIndex = 10; )
  
  layoutAttributesForElements: (-667.0, -667.0, 1042.0, 1334.0)
  
  cell: [0, 0]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fba00&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); frame = (6 56; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6180001fc200&gt; index path: (&lt;NSIndexPath: 0x61800002b7a0&gt; {length = 2, path = 0 - 0}); frame = (-150.5 56; 363 50); )
  
  cell: [0, 1]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fbb00&gt; index path: (&lt;NSIndexPath: 0xc000000000200016&gt; {length = 2, path = 0 - 1}); frame = (68.5 56; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6180001fc300&gt; index path: (&lt;NSIndexPath: 0x61800002b820&gt; {length = 2, path = 0 - 1}); frame = (-88 56; 363 50); )
  
  cell: [0, 2]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fbc00&gt; index path: (&lt;NSIndexPath: 0xc000000000400016&gt; {length = 2, path = 0 - 2}); frame = (131 56; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6180001fc400&gt; index path: (&lt;NSIndexPath: 0x61800002b680&gt; {length = 2, path = 0 - 2}); frame = (-25.5 56; 363 50); )
  
  cell: [1, 0]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fbd00&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); frame = (6 178; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6180001fc500&gt; index path: (&lt;NSIndexPath: 0x61800002b600&gt; {length = 2, path = 1 - 0}); frame = (-150.5 178; 363 50); )
  
  cell: [1, 1]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fbe00&gt; index path: (&lt;NSIndexPath: 0xc000000000200116&gt; {length = 2, path = 1 - 1}); frame = (68.5 178; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6180001fc600&gt; index path: (&lt;NSIndexPath: 0x6180000281a0&gt; {length = 2, path = 1 - 1}); frame = (-88 178; 363 50); )
  
  cell: [1, 2]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fbf00&gt; index path: (&lt;NSIndexPath: 0xc000000000400116&gt; {length = 2, path = 1 - 2}); frame = (131 178; 50 50); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6180001fc700&gt; index path: (&lt;NSIndexPath: 0x6180000296c0&gt; {length = 2, path = 1 - 2}); frame = (-25.5 178; 363 50); )
  
  supp: [0, 0]
  supp_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fc000&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 40); zIndex = 10; 
  Section Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fc800&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 40); zIndex = 10; 
  supp_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6180001fc800&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 40); zIndex = 10; )
  
  supp: [1, 0]
  supp_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6180001fc100&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 122; 375 40); zIndex = 10; 
  Section Attributes: &lt;UICollectionViewLayoutAttributes: 0x6100001fa900&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 122; 375 40); zIndex = 10; 
  supp_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6100001fa900&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 122; 375 40); zIndex = 10; )
  
  layoutAttributesForElements: (-667.0, -667.0, 1042.0, 1334.0)
  
  cell: [0, 0]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e0e00&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); frame = (6 56; 363 45); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000003e1600&gt; index path: (&lt;NSIndexPath: 0x600000233120&gt; {length = 2, path = 0 - 0}); frame = (6 56; 363 45); )
  
  cell: [0, 1]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e0f00&gt; index path: (&lt;NSIndexPath: 0xc000000000200016&gt; {length = 2, path = 0 - 1}); frame = (6 107; 363 45); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000003e1700&gt; index path: (&lt;NSIndexPath: 0x600000233180&gt; {length = 2, path = 0 - 1}); frame = (6 107; 363 45); )
  
  cell: [0, 2]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e1000&gt; index path: (&lt;NSIndexPath: 0xc000000000400016&gt; {length = 2, path = 0 - 2}); frame = (6 158; 363 45); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000003e1800&gt; index path: (&lt;NSIndexPath: 0x6000002331a0&gt; {length = 2, path = 0 - 2}); frame = (6 158; 363 45); )
  
  cell: [1, 0]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e1100&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); frame = (6 275; 363 45); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6080001fa800&gt; index path: (&lt;NSIndexPath: 0x608000035300&gt; {length = 2, path = 1 - 0}); frame = (6 275; 363 45); )
  
  cell: [1, 1]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e1200&gt; index path: (&lt;NSIndexPath: 0xc000000000200116&gt; {length = 2, path = 1 - 1}); frame = (6 326; 363 45); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6080001fb200&gt; index path: (&lt;NSIndexPath: 0x608000035500&gt; {length = 2, path = 1 - 1}); frame = (6 326; 363 45); )
  
  cell: [1, 2]
  cell_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e1300&gt; index path: (&lt;NSIndexPath: 0xc000000000400116&gt; {length = 2, path = 1 - 2}); frame = (6 377; 363 45); 
  cell_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6080001fb100&gt; index path: (&lt;NSIndexPath: 0x608000034d00&gt; {length = 2, path = 1 - 2}); frame = (6 377; 363 45); )
  
  supp: [0, 0]
  supp_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e1400&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 40); zIndex = 10; 
  Section Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e1900&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 40); zIndex = 10; 
  supp_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000003e1900&gt; index path: (&lt;NSIndexPath: 0xc000000000000016&gt; {length = 2, path = 0 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 0; 375 40); zIndex = 10; )
  
  supp: [1, 0]
  supp_old Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e1500&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 219; 375 40); zIndex = 10; 
  Section Attributes: &lt;UICollectionViewLayoutAttributes: 0x6000003e1a00&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 219; 375 40); zIndex = 10; 
  supp_new Attributes: Optional(&lt;UICollectionViewLayoutAttributes: 0x6000003e1a00&gt; index path: (&lt;NSIndexPath: 0xc000000000000116&gt; {length = 2, path = 1 - 0}); element kind: (UICollectionElementKindSectionHeader); frame = (0 219; 375 40); zIndex = 10; )
  </code></pre>
  
  <p>In the final pass of <code>layoutAttributesForElements</code>, the values are correct for both the items and supplementary views, but for some reason the supplementary views are not drawing at that position. They draw at the position in the first two passes.</p>
  
  <p>What's going on here? Why the multiple passes, and why isn't the third pass being used for the supplementary views? Is there a better way to implement this?</p>