AlignedCollectionViewFlowLayout icon indicating copy to clipboard operation
AlignedCollectionViewFlowLayout copied to clipboard

Crash on iPad for iOS 15

Open chamitha opened this issue 2 years ago • 4 comments

I'm getting a crash force unwrapping a nil value testing on iOS 15 Beta but on iPad only. iPhone seems to work fine. The crash occurs here

// It's okay to force-unwrap here because we pass a non-empty array.
return verticalAlignmentAxisForLine(with: layoutAttributesInLine)!

the cause being on iPad super.layoutAttributesForElements called by layoutAttributes(forItemsInLineWith: currentLayoutAttributes) returns nil (and therefore an empty array) whereas on iPhone this returns the layout attributes of the cell. The verticalAlignmentAxisForLine func returns nil if the attributes array is empty therefore causing the force unwrap to crash.

guard let firstAttribute = layoutAttributes.first else {
  return nil
}

Whilst this issue might be fixed in a subsequent beta release I think it exposes a valid issue with the force unwrap. Perhaps a default alignment should be returned by verticalAlignmentAxisForLine instead of nil?

guard let firstAttribute = layoutAttributes.first else {
  return AlignmentAxis(alignment: verticalAlignment, position: 0)
}

chamitha avatar Sep 02 '21 03:09 chamitha

@chamitha I faced the same problem, please try using alignedFlowLayout?.verticalAlignment = .center

JAGUAR108 avatar Sep 08 '21 04:09 JAGUAR108

@chamitha I faced the same problem, please try using alignedFlowLayout?.verticalAlignment = .center

Thanks @JAGUAR108 but I need the vertical alignment to be top.

chamitha avatar Sep 08 '21 04:09 chamitha

I changed the following method to return at least 1 layout attribute, and it looks like it's working.

fileprivate func layoutAttributes(forItemsInLineWith layoutAttributes: UICollectionViewLayoutAttributes) -> [UICollectionViewLayoutAttributes] {
    guard let lineWidth = contentWidth else {
        return [layoutAttributes]
    }
    var lineFrame = layoutAttributes.frame
    lineFrame.origin.x = sectionInset.left
    lineFrame.size.width = lineWidth
    let result = super.layoutAttributesForElements(in: lineFrame)
    if let result = result, !result.isEmpty {
        return result
    } else {
        return [UICollectionViewLayoutAttributes()]
    }
}

CocoaBob avatar Oct 07 '21 03:10 CocoaBob

I changed the following method to return at least 1 layout attribute, and it looks like it's working.

fileprivate func layoutAttributes(forItemsInLineWith layoutAttributes: UICollectionViewLayoutAttributes) -> [UICollectionViewLayoutAttributes] {
    guard let lineWidth = contentWidth else {
        return [layoutAttributes]
    }
    var lineFrame = layoutAttributes.frame
    lineFrame.origin.x = sectionInset.left
    lineFrame.size.width = lineWidth
    let result = super.layoutAttributesForElements(in: lineFrame)
    if let result = result, !result.isEmpty {
        return result
    } else {
        return [UICollectionViewLayoutAttributes()]
    }
}

working.... 💯 🔥

way2dipak avatar Jun 02 '22 17:06 way2dipak