Solving this problem is mostly algebra with a little logic thrown in. First, you need to get the aspect ratio of the collection view, so you know whether you should have more rows or more columns. Once you know that, you can calculate the itemsPerRow, and the numberOfRows. Since you want your cells to be squares, you need to use the smaller of the two sizes that you calculate for how many items will fit in a row or column. When you calculate the sizes, you need to take in to account the minimum spacings in each direction. Here is a little test project that shows how I did it.
#define PLAYERS 4.0
#import "ViewController.h"
@interface ViewController ()
@property (weak,nonatomic) IBOutlet UICollectionView *collectionView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[(UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout setMinimumInteritemSpacing:10];
[(UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout setMinimumLineSpacing:10];
}
-(void)viewDidLayoutSubviews {
CGFloat aspectRatio = (self.collectionView.bounds.size.height/self.collectionView.bounds.size.width);
int itemsPerRow = (aspectRatio > 1)? floorf(pow(PLAYERS,.5)) : ceilf(pow(PLAYERS,.5));
if (aspectRatio >1) {
itemsPerRow = itemsPerRow - (floorf(aspectRatio) - 1);
}else{
itemsPerRow = itemsPerRow - (floorf(1/aspectRatio) - 1);
}
int numberOfRows = ceilf(PLAYERS/itemsPerRow);
CGFloat width = (self.collectionView.bounds.size.width - ((itemsPerRow - 1) *10)) / itemsPerRow;
CGFloat height = (self.collectionView.bounds.size.height - ((numberOfRows - 1) *10)) / numberOfRows;
CGFloat dim = MIN(width, height);
[(UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout setItemSize:CGSizeMake(dim,dim)];
[self.collectionView reloadData];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return PLAYERS;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = @"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
return cell;
}