I've tried a few approaches to create a standard table - with a fixed number of columns and rows, but with variable column widths - for all device classes. The contraint system, even using Stack Views, created an impossible number of layout errors, and so it was suggested to use UICollectionViews, which appears better, but I cannot solve the following issues.
Firstly, the cells in the last row of the table do not align perfectly with the cells above. Each cell is fractionally less width, making the final cell quite clearly unaligned. This issue, while minor in the example project, can appear larger depending on cell contents or device sizes.
Secondly, while I can manage device orientation changes on most devices tested in the simulator, this not true for iPad Air devices. While the table layout is correct when I first run the project on iPad Air in any orientation, and is correct when re-orientated from landscape to horizontal; the layout breaks if I run the project on a iPad Air in portrait orientation, but then rotate to landscape.
To demonstrate these issues, I've put the code below and a very simple project on github (link below). Within the project is a reference to the original source for setting column widths on StackExchange. It would be great if someone with a greater level of undestanding could provide a definitive method, for all devices and in all orientations, to create tables with a fixed number of columns that also have variable widths.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
var columnPortion = CGFloat()
let columnNumber = indexPath.item % 5
switch columnNumber {
case 0:
columnPortion = 0.6
case 1:
columnPortion = 0.3
case 2:
columnPortion = 1
case 3:
columnPortion = 1.4
case 4:
columnPortion = 1.7
default:
columnPortion = 1
}
// https://stackoverflow.com/questions/54915227/uicollectionview-remove-space-between-cells-with-7-items-per-row
var cellWidth = CGFloat()
let availableWidth = collectionView.bounds.size.width
print("available width", availableWidth)
let minimumWidth = floor(availableWidth / numberOfColumns)
print("minmum width", minimumWidth)
cellWidth = minimumWidth * columnPortion - 1 // the - 1 is to remove problems with rounding
print("cell width", cellWidth)
return CGSize(width: cellWidth, height: rowHeight).xx_rounded()
}