It seems that there is currently no easy way:
- Extract prototype prototypes of UICollectionViewCell from the storyboard (s).
- Manage prototype sizes in only one place (instead of entering them in the prototype of the Storyboard cell and implementing
sizeForItemAtIndexPath ).
The proposed method here (for UITableViews) does not work, since using dequeueReusableCellWithReuseIdentifier in sizeForItemAtIndexPath will lead to an undefined loop.
However, I managed to do it as follows :
Add a unique (across all UICollectionViewCell in each storyboard) reuse identifier to each of your prototype UICollectionView in all storyboards.
Add a Run script build phase to the project using a script that pulls the frame sizes of the UICollectionViewCell from all the storyboards.
output=${PROJECT_DIR}/StoryboardPrototypeCellSizes.h printf "@{" > $output for storyboard in $(find ${PROJECT_DIR} -name "*.storyboard") do echo "Scanning storyboard $storyboard..." delimiter= for line in $(xpath $storyboard "//collectionViewCell/@reuseIdentifier[string-length()>0] | //collectionViewCell/rect" 2>&-) do case $line in reuseIdentifier*) reuseIdentifier=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) ;; width*) if [ -n "$reuseIdentifier" ]; then width=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) fi ;; height*) if [ -n "$reuseIdentifier" ]; then height=$(sed 's/[^"]*"\([^"]*\)".*/\1/' <<< $line) fi ;; esac if [ -n "$reuseIdentifier" ] && [ -n "$width" ] && [ -n "$height" ]; then printf " $delimiter@ \"$reuseIdentifier\" : [NSValue valueWithCGSize:CGSizeMake($width, $height)]" >> $output unset reuseIdentifier unset width unset height delimiter=,\\n fi done done printf "};\n" >> $output
This creates a header file called StoryboardPrototypeCellSizes.h with the following example:
@{@"TodayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 80)], @"SpecialDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 42)], @"NameDayCell" : [NSValue valueWithCGSize:CGSizeMake(320, 30)]};
Add a helper method to return the reuse identifier of the UICollectionViewCell in the view controller that controls your UICollectionView :
- (NSString *)cellReuseIdentifierAtIndexPath:(NSIndexPath *)indexPath { switch (indexPath.item) { case 0: return @"TodayCell"; case 1: return @"SpecialDayCell"; case 2: return @"NameDayCell"; } return nil; }
Be sure to use the same reuse identifier in cellForItemAtIndexPath :
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: [self cellReuseIdentifierAtIndexPath:indexPath] forIndexPath:indexPath]; ...
Finally, execute sizeForItemAtIndexPath :
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { NSDictionary *storyboardPrototypeCellSizes = #import "StoryboardPrototypeCellSizes.h" return [(NSValue *)storyboardPrototypeCellSizes[ [self cellReuseIdentifierAtIndexPath:indexPath] ] CGSizeValue]; }
This solution allows you to determine the cell sizes of the prototype UICollectionViewCell only once in the storyboard (s), and also does not perform compatibility with non-App-Store at run time.
**** Editing: **** You can also select UICollectionReusableView sizes by adding another script with the same contents and replacing "collectionViewCell" with "collectionReusableView" and renaming the header file, for example, in StoryboardReusableViewSizes.h
source share