sizeForItemAtIndexPath getting called for all indexes before load - I am pretty sure I am either running into...












1














I am able to reproduce this on a very simple standalone app.



I have a collectionView which I want to make circular/loop so the elements repeat again and again (aka when user is at the last element in array, it shows the first element again after. And if they are at the first and scroll left, it shows the last element again). So it's a never ending collectionView.



So for a simple example, let's use days of week:



....Sunday, Monday, Tuesday, Wednesday..Saturday, Sunday, Monday....



In order to achieve this, I return a big number (10000) in the numberOfItemsInSection and use indexPath.item%7 in the cellForItemAtIndexPath method to adjust and get the correct element. Using %7 as there are 7 days.
My cells are very simple - just a UILabel in it.



This all works perfectly.



The issue comes with the sizeForItemAtIndexPath. I want the cells to fit the label. As there would only be 7 actual size variations, so I pre-cache the sizes of the 7 days in a dictionary and return the correct size in sizeForItemAtIndexPath method.



The problem is that (either due to a bug or intentional bad design by Apple of collectionview), the sizeForItemAtIndexPath gets calls for every indexPath before the collectionview appears. So if I want to have the circular collectionView logic and need to return the big number (10000), it's is calling sizeForItemAtIndexPath for all 10000 indexes. So there is a couple seconds lag until the collectionView appears. If I comment out the sizeForItemAtIndexPath, then it works instantly. So that's definitely the issue. I put a NSLog in the sizeForItemAtIndexPath and it logs all the 22222 calls before load.



I have even defined the setEstimatedItemSize, it still calls sizeForItemAtIndexPath for all indexes.



I can reduce the lag by returning a smaller number 1000 but still, this is a bad design or bug for sure.



TableView doesn't have this bug - you can define a million rows and it only calls the heightForRow when it actually needs it. So I am not sure why collectionView needs to call it for all cells before showing, especially if setEstimatedItemSize is already defined too.



Another side-effect of this bug is that the collectionView throws an error if I return a bigger value (50000 makes it break, 22222 is okay). It prints the error for too big values:



This NSLayoutConstraint is being configured with a constant that exceeds internal limits.  A smaller value will be substituted, but this problem should be fixed. Break on BOOL _NSLayoutConstraintNumberExceedsLimit(void) to debug.  This will be logged only once.  This may break in the future.


TableView can easily handle huge values because it doesn't have this bug.



I have also tried disabling prefetching but that had no effect.



What do you all think?



Relevant code:



#define kInfiniteCount 22222
#define kDayNameMargin 30

@interface ViewController (){
NSMutableDictionary *dictOfSizes;
}

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
self.myCalendar = [NSCalendar currentCalendar];
[self.myCalendar setLocale:locale];

dictOfSizes = [NSMutableDictionary new];

for (int i=0; i<7; i++) {
WeekdayCollectionViewCell *sizingCell = [[NSBundle mainBundle] loadNibNamed:@"WeekdayCell" owner:self options:nil][0];
sizingCell.myLabel.text=[self.myCalendar weekdaySymbols][i];
[sizingCell layoutIfNeeded];

[dictOfSizes setObject:[NSValue valueWithCGSize:[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]] forKey:sizingCell.myLabel.text];
}



self.myCollectionView.decelerationRate = UIScrollViewDecelerationRateFast;
[self.myCollectionView registerNib:[UINib nibWithNibName:@"WeekdayCell" bundle:nil] forCellWithReuseIdentifier:@"daycell"];
[(UICollectionViewFlowLayout*)self.myCollectionView.collectionViewLayout setEstimatedItemSize:CGSizeMake(200, self.myCollectionView.frame.size.height)];
[self.myCollectionView reloadData];


NSInteger middleGoTo = kInfiniteCount/2;

while (![[self.myCalendar weekdaySymbols][middleGoTo%7] isEqualToString:@"Monday"]) {
middleGoTo--;
}

[self.myCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:middleGoTo inSection:0] atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return kInfiniteCount;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
WeekdayCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"daycell" forIndexPath:indexPath];

cell.myLabel.text=[self.myCalendar weekdaySymbols][indexPath.item%7];
return cell;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"sizeForItemAtIndexPath: %ld",indexPath.item);
return [(NSValue*)[dictOfSizes objectForKey:[self.myCalendar weekdaySymbols][indexPath.item%7]] CGSizeValue];
}


EDIT:



Few people mentioned using scrollview instead of collectionview for this.



Pretty much everywhere I researched for the circular scrollview, they recommended using a collectionview for this purpose as it's much easier. My real requirement is a bit more complex which requires me to use collectionview too.



Scrollview requires you to use the scrollViewDidScroll method and change the content offset each time. Plus it loads all views in memory at once as it doesn't have the advantage of reusing existing cells like collectionview does. So that's another memory hit.



The 7 weekdays is a simple example I used. If someone wants to show a lot of data (100), that would be a pretty bad implementation in scrollview and collectionview will present this bug.










share|improve this question





























    1














    I am able to reproduce this on a very simple standalone app.



    I have a collectionView which I want to make circular/loop so the elements repeat again and again (aka when user is at the last element in array, it shows the first element again after. And if they are at the first and scroll left, it shows the last element again). So it's a never ending collectionView.



    So for a simple example, let's use days of week:



    ....Sunday, Monday, Tuesday, Wednesday..Saturday, Sunday, Monday....



    In order to achieve this, I return a big number (10000) in the numberOfItemsInSection and use indexPath.item%7 in the cellForItemAtIndexPath method to adjust and get the correct element. Using %7 as there are 7 days.
    My cells are very simple - just a UILabel in it.



    This all works perfectly.



    The issue comes with the sizeForItemAtIndexPath. I want the cells to fit the label. As there would only be 7 actual size variations, so I pre-cache the sizes of the 7 days in a dictionary and return the correct size in sizeForItemAtIndexPath method.



    The problem is that (either due to a bug or intentional bad design by Apple of collectionview), the sizeForItemAtIndexPath gets calls for every indexPath before the collectionview appears. So if I want to have the circular collectionView logic and need to return the big number (10000), it's is calling sizeForItemAtIndexPath for all 10000 indexes. So there is a couple seconds lag until the collectionView appears. If I comment out the sizeForItemAtIndexPath, then it works instantly. So that's definitely the issue. I put a NSLog in the sizeForItemAtIndexPath and it logs all the 22222 calls before load.



    I have even defined the setEstimatedItemSize, it still calls sizeForItemAtIndexPath for all indexes.



    I can reduce the lag by returning a smaller number 1000 but still, this is a bad design or bug for sure.



    TableView doesn't have this bug - you can define a million rows and it only calls the heightForRow when it actually needs it. So I am not sure why collectionView needs to call it for all cells before showing, especially if setEstimatedItemSize is already defined too.



    Another side-effect of this bug is that the collectionView throws an error if I return a bigger value (50000 makes it break, 22222 is okay). It prints the error for too big values:



    This NSLayoutConstraint is being configured with a constant that exceeds internal limits.  A smaller value will be substituted, but this problem should be fixed. Break on BOOL _NSLayoutConstraintNumberExceedsLimit(void) to debug.  This will be logged only once.  This may break in the future.


    TableView can easily handle huge values because it doesn't have this bug.



    I have also tried disabling prefetching but that had no effect.



    What do you all think?



    Relevant code:



    #define kInfiniteCount 22222
    #define kDayNameMargin 30

    @interface ViewController (){
    NSMutableDictionary *dictOfSizes;
    }

    @end

    @implementation ViewController

    - (void)viewDidLoad {
    [super viewDidLoad];
    NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    self.myCalendar = [NSCalendar currentCalendar];
    [self.myCalendar setLocale:locale];

    dictOfSizes = [NSMutableDictionary new];

    for (int i=0; i<7; i++) {
    WeekdayCollectionViewCell *sizingCell = [[NSBundle mainBundle] loadNibNamed:@"WeekdayCell" owner:self options:nil][0];
    sizingCell.myLabel.text=[self.myCalendar weekdaySymbols][i];
    [sizingCell layoutIfNeeded];

    [dictOfSizes setObject:[NSValue valueWithCGSize:[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]] forKey:sizingCell.myLabel.text];
    }



    self.myCollectionView.decelerationRate = UIScrollViewDecelerationRateFast;
    [self.myCollectionView registerNib:[UINib nibWithNibName:@"WeekdayCell" bundle:nil] forCellWithReuseIdentifier:@"daycell"];
    [(UICollectionViewFlowLayout*)self.myCollectionView.collectionViewLayout setEstimatedItemSize:CGSizeMake(200, self.myCollectionView.frame.size.height)];
    [self.myCollectionView reloadData];


    NSInteger middleGoTo = kInfiniteCount/2;

    while (![[self.myCalendar weekdaySymbols][middleGoTo%7] isEqualToString:@"Monday"]) {
    middleGoTo--;
    }

    [self.myCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:middleGoTo inSection:0] atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
    }

    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return kInfiniteCount;
    }

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    WeekdayCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"daycell" forIndexPath:indexPath];

    cell.myLabel.text=[self.myCalendar weekdaySymbols][indexPath.item%7];
    return cell;
    }

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"sizeForItemAtIndexPath: %ld",indexPath.item);
    return [(NSValue*)[dictOfSizes objectForKey:[self.myCalendar weekdaySymbols][indexPath.item%7]] CGSizeValue];
    }


    EDIT:



    Few people mentioned using scrollview instead of collectionview for this.



    Pretty much everywhere I researched for the circular scrollview, they recommended using a collectionview for this purpose as it's much easier. My real requirement is a bit more complex which requires me to use collectionview too.



    Scrollview requires you to use the scrollViewDidScroll method and change the content offset each time. Plus it loads all views in memory at once as it doesn't have the advantage of reusing existing cells like collectionview does. So that's another memory hit.



    The 7 weekdays is a simple example I used. If someone wants to show a lot of data (100), that would be a pretty bad implementation in scrollview and collectionview will present this bug.










    share|improve this question



























      1












      1








      1







      I am able to reproduce this on a very simple standalone app.



      I have a collectionView which I want to make circular/loop so the elements repeat again and again (aka when user is at the last element in array, it shows the first element again after. And if they are at the first and scroll left, it shows the last element again). So it's a never ending collectionView.



      So for a simple example, let's use days of week:



      ....Sunday, Monday, Tuesday, Wednesday..Saturday, Sunday, Monday....



      In order to achieve this, I return a big number (10000) in the numberOfItemsInSection and use indexPath.item%7 in the cellForItemAtIndexPath method to adjust and get the correct element. Using %7 as there are 7 days.
      My cells are very simple - just a UILabel in it.



      This all works perfectly.



      The issue comes with the sizeForItemAtIndexPath. I want the cells to fit the label. As there would only be 7 actual size variations, so I pre-cache the sizes of the 7 days in a dictionary and return the correct size in sizeForItemAtIndexPath method.



      The problem is that (either due to a bug or intentional bad design by Apple of collectionview), the sizeForItemAtIndexPath gets calls for every indexPath before the collectionview appears. So if I want to have the circular collectionView logic and need to return the big number (10000), it's is calling sizeForItemAtIndexPath for all 10000 indexes. So there is a couple seconds lag until the collectionView appears. If I comment out the sizeForItemAtIndexPath, then it works instantly. So that's definitely the issue. I put a NSLog in the sizeForItemAtIndexPath and it logs all the 22222 calls before load.



      I have even defined the setEstimatedItemSize, it still calls sizeForItemAtIndexPath for all indexes.



      I can reduce the lag by returning a smaller number 1000 but still, this is a bad design or bug for sure.



      TableView doesn't have this bug - you can define a million rows and it only calls the heightForRow when it actually needs it. So I am not sure why collectionView needs to call it for all cells before showing, especially if setEstimatedItemSize is already defined too.



      Another side-effect of this bug is that the collectionView throws an error if I return a bigger value (50000 makes it break, 22222 is okay). It prints the error for too big values:



      This NSLayoutConstraint is being configured with a constant that exceeds internal limits.  A smaller value will be substituted, but this problem should be fixed. Break on BOOL _NSLayoutConstraintNumberExceedsLimit(void) to debug.  This will be logged only once.  This may break in the future.


      TableView can easily handle huge values because it doesn't have this bug.



      I have also tried disabling prefetching but that had no effect.



      What do you all think?



      Relevant code:



      #define kInfiniteCount 22222
      #define kDayNameMargin 30

      @interface ViewController (){
      NSMutableDictionary *dictOfSizes;
      }

      @end

      @implementation ViewController

      - (void)viewDidLoad {
      [super viewDidLoad];
      NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
      self.myCalendar = [NSCalendar currentCalendar];
      [self.myCalendar setLocale:locale];

      dictOfSizes = [NSMutableDictionary new];

      for (int i=0; i<7; i++) {
      WeekdayCollectionViewCell *sizingCell = [[NSBundle mainBundle] loadNibNamed:@"WeekdayCell" owner:self options:nil][0];
      sizingCell.myLabel.text=[self.myCalendar weekdaySymbols][i];
      [sizingCell layoutIfNeeded];

      [dictOfSizes setObject:[NSValue valueWithCGSize:[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]] forKey:sizingCell.myLabel.text];
      }



      self.myCollectionView.decelerationRate = UIScrollViewDecelerationRateFast;
      [self.myCollectionView registerNib:[UINib nibWithNibName:@"WeekdayCell" bundle:nil] forCellWithReuseIdentifier:@"daycell"];
      [(UICollectionViewFlowLayout*)self.myCollectionView.collectionViewLayout setEstimatedItemSize:CGSizeMake(200, self.myCollectionView.frame.size.height)];
      [self.myCollectionView reloadData];


      NSInteger middleGoTo = kInfiniteCount/2;

      while (![[self.myCalendar weekdaySymbols][middleGoTo%7] isEqualToString:@"Monday"]) {
      middleGoTo--;
      }

      [self.myCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:middleGoTo inSection:0] atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
      }

      - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
      return kInfiniteCount;
      }

      - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
      WeekdayCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"daycell" forIndexPath:indexPath];

      cell.myLabel.text=[self.myCalendar weekdaySymbols][indexPath.item%7];
      return cell;
      }

      - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
      NSLog(@"sizeForItemAtIndexPath: %ld",indexPath.item);
      return [(NSValue*)[dictOfSizes objectForKey:[self.myCalendar weekdaySymbols][indexPath.item%7]] CGSizeValue];
      }


      EDIT:



      Few people mentioned using scrollview instead of collectionview for this.



      Pretty much everywhere I researched for the circular scrollview, they recommended using a collectionview for this purpose as it's much easier. My real requirement is a bit more complex which requires me to use collectionview too.



      Scrollview requires you to use the scrollViewDidScroll method and change the content offset each time. Plus it loads all views in memory at once as it doesn't have the advantage of reusing existing cells like collectionview does. So that's another memory hit.



      The 7 weekdays is a simple example I used. If someone wants to show a lot of data (100), that would be a pretty bad implementation in scrollview and collectionview will present this bug.










      share|improve this question















      I am able to reproduce this on a very simple standalone app.



      I have a collectionView which I want to make circular/loop so the elements repeat again and again (aka when user is at the last element in array, it shows the first element again after. And if they are at the first and scroll left, it shows the last element again). So it's a never ending collectionView.



      So for a simple example, let's use days of week:



      ....Sunday, Monday, Tuesday, Wednesday..Saturday, Sunday, Monday....



      In order to achieve this, I return a big number (10000) in the numberOfItemsInSection and use indexPath.item%7 in the cellForItemAtIndexPath method to adjust and get the correct element. Using %7 as there are 7 days.
      My cells are very simple - just a UILabel in it.



      This all works perfectly.



      The issue comes with the sizeForItemAtIndexPath. I want the cells to fit the label. As there would only be 7 actual size variations, so I pre-cache the sizes of the 7 days in a dictionary and return the correct size in sizeForItemAtIndexPath method.



      The problem is that (either due to a bug or intentional bad design by Apple of collectionview), the sizeForItemAtIndexPath gets calls for every indexPath before the collectionview appears. So if I want to have the circular collectionView logic and need to return the big number (10000), it's is calling sizeForItemAtIndexPath for all 10000 indexes. So there is a couple seconds lag until the collectionView appears. If I comment out the sizeForItemAtIndexPath, then it works instantly. So that's definitely the issue. I put a NSLog in the sizeForItemAtIndexPath and it logs all the 22222 calls before load.



      I have even defined the setEstimatedItemSize, it still calls sizeForItemAtIndexPath for all indexes.



      I can reduce the lag by returning a smaller number 1000 but still, this is a bad design or bug for sure.



      TableView doesn't have this bug - you can define a million rows and it only calls the heightForRow when it actually needs it. So I am not sure why collectionView needs to call it for all cells before showing, especially if setEstimatedItemSize is already defined too.



      Another side-effect of this bug is that the collectionView throws an error if I return a bigger value (50000 makes it break, 22222 is okay). It prints the error for too big values:



      This NSLayoutConstraint is being configured with a constant that exceeds internal limits.  A smaller value will be substituted, but this problem should be fixed. Break on BOOL _NSLayoutConstraintNumberExceedsLimit(void) to debug.  This will be logged only once.  This may break in the future.


      TableView can easily handle huge values because it doesn't have this bug.



      I have also tried disabling prefetching but that had no effect.



      What do you all think?



      Relevant code:



      #define kInfiniteCount 22222
      #define kDayNameMargin 30

      @interface ViewController (){
      NSMutableDictionary *dictOfSizes;
      }

      @end

      @implementation ViewController

      - (void)viewDidLoad {
      [super viewDidLoad];
      NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
      self.myCalendar = [NSCalendar currentCalendar];
      [self.myCalendar setLocale:locale];

      dictOfSizes = [NSMutableDictionary new];

      for (int i=0; i<7; i++) {
      WeekdayCollectionViewCell *sizingCell = [[NSBundle mainBundle] loadNibNamed:@"WeekdayCell" owner:self options:nil][0];
      sizingCell.myLabel.text=[self.myCalendar weekdaySymbols][i];
      [sizingCell layoutIfNeeded];

      [dictOfSizes setObject:[NSValue valueWithCGSize:[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]] forKey:sizingCell.myLabel.text];
      }



      self.myCollectionView.decelerationRate = UIScrollViewDecelerationRateFast;
      [self.myCollectionView registerNib:[UINib nibWithNibName:@"WeekdayCell" bundle:nil] forCellWithReuseIdentifier:@"daycell"];
      [(UICollectionViewFlowLayout*)self.myCollectionView.collectionViewLayout setEstimatedItemSize:CGSizeMake(200, self.myCollectionView.frame.size.height)];
      [self.myCollectionView reloadData];


      NSInteger middleGoTo = kInfiniteCount/2;

      while (![[self.myCalendar weekdaySymbols][middleGoTo%7] isEqualToString:@"Monday"]) {
      middleGoTo--;
      }

      [self.myCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:middleGoTo inSection:0] atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
      }

      - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
      return kInfiniteCount;
      }

      - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
      WeekdayCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"daycell" forIndexPath:indexPath];

      cell.myLabel.text=[self.myCalendar weekdaySymbols][indexPath.item%7];
      return cell;
      }

      - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
      NSLog(@"sizeForItemAtIndexPath: %ld",indexPath.item);
      return [(NSValue*)[dictOfSizes objectForKey:[self.myCalendar weekdaySymbols][indexPath.item%7]] CGSizeValue];
      }


      EDIT:



      Few people mentioned using scrollview instead of collectionview for this.



      Pretty much everywhere I researched for the circular scrollview, they recommended using a collectionview for this purpose as it's much easier. My real requirement is a bit more complex which requires me to use collectionview too.



      Scrollview requires you to use the scrollViewDidScroll method and change the content offset each time. Plus it loads all views in memory at once as it doesn't have the advantage of reusing existing cells like collectionview does. So that's another memory hit.



      The 7 weekdays is a simple example I used. If someone wants to show a lot of data (100), that would be a pretty bad implementation in scrollview and collectionview will present this bug.







      ios objective-c swift uicollectionview uicollectionviewlayout






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 23 '18 at 22:59









      Tamás Sengel

      26.6k146793




      26.6k146793










      asked Nov 23 '18 at 22:57









      Pranoy CPranoy C

      4,15583460




      4,15583460
























          1 Answer
          1






          active

          oldest

          votes


















          0














          That's expected behaviour and it's not so much related to UICollectionView - it is more UICollectionViewFlowLayout that you use.



          With each cell being different size, FlowLayout will request sizes for each cell separately, to calculate total size of CollectionView - that is required to properly handle scrolling, scrollbars.



          UITableView it's a bit simpler, as it's layout is much simpler (only height matters) - that's why it's possible to use estimatedSize there.



          The whole Core Layout Process is well explained here:



          https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html



          To overcome this problem I would recommend using your custom UICollectionViewLayout and move your caching logic and reusing sizes for cells inside CollectionViewLayout, not in your ViewController.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53453681%2fsizeforitematindexpath-getting-called-for-all-indexes-before-load-i-am-pretty%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            That's expected behaviour and it's not so much related to UICollectionView - it is more UICollectionViewFlowLayout that you use.



            With each cell being different size, FlowLayout will request sizes for each cell separately, to calculate total size of CollectionView - that is required to properly handle scrolling, scrollbars.



            UITableView it's a bit simpler, as it's layout is much simpler (only height matters) - that's why it's possible to use estimatedSize there.



            The whole Core Layout Process is well explained here:



            https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html



            To overcome this problem I would recommend using your custom UICollectionViewLayout and move your caching logic and reusing sizes for cells inside CollectionViewLayout, not in your ViewController.






            share|improve this answer




























              0














              That's expected behaviour and it's not so much related to UICollectionView - it is more UICollectionViewFlowLayout that you use.



              With each cell being different size, FlowLayout will request sizes for each cell separately, to calculate total size of CollectionView - that is required to properly handle scrolling, scrollbars.



              UITableView it's a bit simpler, as it's layout is much simpler (only height matters) - that's why it's possible to use estimatedSize there.



              The whole Core Layout Process is well explained here:



              https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html



              To overcome this problem I would recommend using your custom UICollectionViewLayout and move your caching logic and reusing sizes for cells inside CollectionViewLayout, not in your ViewController.






              share|improve this answer


























                0












                0








                0






                That's expected behaviour and it's not so much related to UICollectionView - it is more UICollectionViewFlowLayout that you use.



                With each cell being different size, FlowLayout will request sizes for each cell separately, to calculate total size of CollectionView - that is required to properly handle scrolling, scrollbars.



                UITableView it's a bit simpler, as it's layout is much simpler (only height matters) - that's why it's possible to use estimatedSize there.



                The whole Core Layout Process is well explained here:



                https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html



                To overcome this problem I would recommend using your custom UICollectionViewLayout and move your caching logic and reusing sizes for cells inside CollectionViewLayout, not in your ViewController.






                share|improve this answer














                That's expected behaviour and it's not so much related to UICollectionView - it is more UICollectionViewFlowLayout that you use.



                With each cell being different size, FlowLayout will request sizes for each cell separately, to calculate total size of CollectionView - that is required to properly handle scrolling, scrollbars.



                UITableView it's a bit simpler, as it's layout is much simpler (only height matters) - that's why it's possible to use estimatedSize there.



                The whole Core Layout Process is well explained here:



                https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html



                To overcome this problem I would recommend using your custom UICollectionViewLayout and move your caching logic and reusing sizes for cells inside CollectionViewLayout, not in your ViewController.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 24 '18 at 2:39

























                answered Nov 24 '18 at 1:57









                Grzegorz KrukowskiGrzegorz Krukowski

                10.6k32850




                10.6k32850






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53453681%2fsizeforitematindexpath-getting-called-for-all-indexes-before-load-i-am-pretty%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Contact image not getting when fetch all contact list from iPhone by CNContact

                    count number of partitions of a set with n elements into k subsets

                    A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks