3

I am writing an app which makes use of UICollectionView to display some content in the CollectionView Cells. With pinch gestures, the collection view needs to be reloaded. I am able to handle the change of content according to the pinch gestures. Now, on the pinch gesture START, the collection view needs to reloaded and scrolled to a specific index. To do that, I have called the functions like this:

[tempCollectionView reloadData];

[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(scrollToItem)  userInfo:nil repeats:YES];

[OR]
[self performSelector:@selector(scrollToItem) withObject:nil afterDelay:0.0];

- (void) scrollToItem 
{
    if (m_selectedCellIndex == -1) 
    {
        NSLog(@"cell return");
        return;
    }

    NSIndexPath *iPath = [NSIndexPath indexPathForItem:m_selectedCellIndex inSection:0];
    [tempLocalFilesCollectionView scrollToItemAtIndexPath:iPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];

    LocalFilesCollectionViewCell *cell = (LocalFilesCollectionViewCell *) [m_tempLocalFilesCollectionView cellForItemAtIndexPath: iPath];
    if (cell) 
    {
        CGPoint p = [tempCollectionView convertPoint: cell.center fromView: tempCollectionView];
        NSLog(@"center: %f, %f,  %f, %f", cell.center.x, cell.center.y, p.x, p.y);
    }
    else 
    {
        NSLog(@"Not found");
    }
}

But the scroll doesn't work. It crashes with the error "attempt to scroll to invalid index path". It is obvious that the tempCollectionView doesn't have any cells ready to be scrolled.

How can I scroll to the index path after the reload is finished? Any help would be great!!

user862972
  • 224
  • 5
  • 13
  • You should be able to just call the scroll method immediately after refreshing the collection view. It is an issue with your indexpath. Have you printed out `iPath`'s row? Is it larger or smaller than the amount of views you have? – Firo Nov 05 '13 at 16:54
  • iPath's row looks to be correct, within the limits of the count of cells. More than the scrolling, my intention is to get the cell's position through this. The cell is returned as nil in the above method. Am I missing something here? – user862972 Nov 06 '13 at 08:24
  • You are calling scrollToItem twice. Once delayed and once without delay. It is possible that the reloadData hasn't completed for the call without delay to have any indexpaths to work with. – Daniel Nordh Nov 06 '13 at 11:49
  • I forgot to put an OR there, I am trying to call with either one of the two statements written there. Thanks! – user862972 Nov 06 '13 at 14:55

3 Answers3

0

Try This

BOOL _viewDidLayoutSubviewsForTheFirstTime = YES;

- (void)viewDidLoad
{
  [super viewDidLoad];
  _viewDidLayoutSubviewsForTheFirstTime = YES;
}

- (void)viewDidLayoutSubviews
{
  [super viewDidLayoutSubviews];
  // Only scroll when the view is rendered for the first time
  if (_viewDidLayoutSubviewsForTheFirstTime) {
    _viewDidLayoutSubviewsForTheFirstTime = NO;
    // Calling collectionViewContentSize forces the UICollectionViewLayout to actually render the layout
    [self.collectionView.collectionViewLayout collectionViewContentSize];
    // Now you can scroll to your desired indexPath or contentOffset
    [self.collectionView scrollToItemAtIndexPath:yourDesiredIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];
  }
}

Hope it is helpful to someone

Prashant Tukadiya
  • 15,838
  • 4
  • 62
  • 98
0

The best solution I have found so far is to use CATransaction like this:

CATransaction.begin()
CATransaction.setCompletionBlock {
    collectionView.scrollToItem(...)
}

collectionView.reloadData()

CATransaction.commit()
-1

you can try this async code if you want to scroll Vertical

dispatch_async(dispatch_get_main_queue(), ^{
    [_yourCollectionView reloadData];
    [_yourCollectionView reloadInputViews];
    [_yourCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:5 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
});

and replace with

[_yourCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:5 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];

if you want your scroll view scroll Horizontal

replace the number of indexPathForRow and inSection with your row number you want to scroll to, and remember NSIndexPath for UITableView and UICollectionView often come with inSection references Convert NSInteger to NSIndexpath

Community
  • 1
  • 1