Group Group Group Group Group Group Group Group Group

Possible solution to challenge: Calculating the tile grid (p. 997, chapter 50)

I tried my hand at the challenge proposed in the “Landscape” chapter 50 on p. 997 (page 988 and chapter 39 old version). The challenge was to avoid hard coding the values of the item height and width as well as the margins but instead to come up with a way of calculating them for any possible screen size.

My solution might be a bit clumsy and has duplicate code in it, but it compiles and gets the job done - as far as I can tell. You just need to define values for the minimum and maximum item width/height as well as values for the desired margins:

let viewWidth = scrollView.bounds.size.width
let viewHeight = scrollView.bounds.size.height

let buttonWidth = 82
let buttonHeight = 82

let minItemWidth = buttonWidth + 6
let maxItemWidth = buttonWidth + 16

let minItemHeight = buttonHeight + 6
let maxItemHeight = buttonHeight + 16

let minMarginWidth = 0
let maxMarginWidth = 20

let minMarginHeight = 0
let maxMarginHeight = 30

var maxPossibleRows = 0
var finalItemHeight = 0
var finalMarginHeight = 0

let heightValueArray = ((viewHeight - maxItemHeight)+1...viewHeight)
    .filter { $0 % 2 == 0 }

for height in heightValueArray {
    for itemHeight in minItemHeight...maxItemHeight where (viewHeight % itemHeight) / 2 <= maxMarginHeight && (viewHeight % itemHeight) / 2 >= minMarginHeight {
        let numberOfRows = height / itemHeight
        if numberOfRows > maxPossibleRows {
            maxPossibleRows = numberOfRows
            finalItemHeight = itemHeight
            finalMarginHeight = (viewHeight % itemHeight) / 2
        }
    }
}

var maxPossibleColumns = 0
var finalItemWidth = 0
var finalMarginWidth = 0

let widthValueArray = ((viewWidth - maxItemWidth)+1...viewWidth)
    .filter { $0 % 2 == 0 }

for width in widthValueArray {
    for itemWidth in minItemWidth...maxItemWidth where (viewWidth % itemWidth) / 2 <= maxMarginWidth && (viewWidth % itemWidth) / 2 >= minMarginWidth {
        let numberOfColumns = width / itemWidth
        if numberOfColumns > maxPossibleColumns {
            maxPossibleColumns = numberOfColumns
            finalItemWidth = itemWidth
            finalMarginWidth = (viewWidth % itemWidth) / 2
        }
    }
}

Please let me know what you think.