NSCollectionViewFlowLayout produces a layout with items justified on the right margin or, if the container is only wide enough for one item, centres items. I was expecting an alignment option, e.g. on the delegate, but am not finding anything in the docs. Does it require subclassing NSCollectionViewFlowLayout to achieve this?
Here is a subclass that produces a left justified flow layout:
class LeftFlowLayout: NSCollectionViewFlowLayout {
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [NSCollectionViewLayoutAttributes] {
        let defaultAttributes = super.layoutAttributesForElementsInRect(rect)
        if defaultAttributes.isEmpty {
            // we rely on 0th element being present,
            // bail if missing (when there's no work to do anyway)
            return defaultAttributes
        }
        var leftAlignedAttributes = [NSCollectionViewLayoutAttributes]()
        var xCursor = self.sectionInset.left // left margin
        // if/when there is a new row, we want to start at left margin
        // the default FlowLayout will sometimes centre items,
        // i.e. new rows do not always start at the left edge
        var lastYPosition = defaultAttributes[0].frame.origin.y
        for attributes in defaultAttributes {
            if attributes.frame.origin.y > lastYPosition {
                // we have changed line
                xCursor = self.sectionInset.left
                lastYPosition = attributes.frame.origin.y
            }
            attributes.frame.origin.x = xCursor
            // by using the minimumInterimitemSpacing we no we'll never go
            // beyond the right margin, so no further checks are required
            xCursor += attributes.frame.size.width + minimumInteritemSpacing
            leftAlignedAttributes.append(attributes)
        }
        return leftAlignedAttributes
    }
}
@Obliquely's answer fails when the collectionViewItems are not uniform in height. Here is their code modified to handle non-uniformly-sized items in Swift 4.2:
class CollectionViewLeftFlowLayout: NSCollectionViewFlowLayout
{
    override func layoutAttributesForElements(in rect: CGRect) -> [NSCollectionViewLayoutAttributes]
    {
        let defaultAttributes = super.layoutAttributesForElements(in: rect)
        if defaultAttributes.isEmpty {
            return defaultAttributes
        }
        var leftAlignedAttributes = [NSCollectionViewLayoutAttributes]()
        var xCursor = self.sectionInset.left                            // left margin
        var lastYPosition = defaultAttributes[0].frame.origin.y         // if/when there is a new row, we want to start at left margin
        var lastItemHeight = defaultAttributes[0].frame.size.height
        for attributes in defaultAttributes
        {
            // copy() Needed to avoid warning from CollectionView that cached values are mismatched
            guard let newAttributes = attributes.copy() as? NSCollectionViewLayoutAttributes else {
                continue;
            }
            if newAttributes.frame.origin.y > (lastYPosition + lastItemHeight)
            {
                // We have started a new row
                xCursor = self.sectionInset.left
                lastYPosition = newAttributes.frame.origin.y
            }
            newAttributes.frame.origin.x = xCursor
            xCursor += newAttributes.frame.size.width + minimumInteritemSpacing
            lastItemHeight = newAttributes.frame.size.height
            leftAlignedAttributes.append(newAttributes)
        }
        return leftAlignedAttributes
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With