4

I have a UIViewController subclass that contains a UICollectionView. Selecting a cell presents a new view controller. When I return to the first view controller, the contentOffset of the collection view is reset to CGPointZero.

From my research this seems to be standard behaviour.

I can reset the contentOffset by adding a private property to my view controller subclass, saving the contentOffset in the viewWillDissapear method and resetting it on the collection view in the viewWillAppear method.

I would like to know though, is there another way to prevent the scroll view content offset from being reset in the first place (removing the need for an extra property)?

I am targetting iOS7.

The 2nd view controller is presented like this:

[self presentViewController:secondVC animated:YES completion:nil];

And dismissed like this (in the 2nd view controller):

-(void) dismiss
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

Edit: After further investigation it appears resetting the contentOffset is not the default behaviour. I haven't figured out why it is happening in my application yet. I am presenting just as have showed in the code above.

Darren
  • 9,855
  • 18
  • 60
  • 106
  • Why do you want another method, I think this method works fine – ukim Jul 21 '14 at 02:39
  • For one thing I find this method messy. For another, when the contentOffset is reset to 0, the previously visible cells are reused. I am downloading images from a url, so when I go back to the view and reset the contentOffset, I need to redownload the images. This may not be an issue once I have proper caching in place, but I would still prefer this not happen. – Darren Jul 21 '14 at 12:53
  • 1
    I don't see this behavior in my app (iOS 7.1). The content offset is not changed when I come back from a modal presentation. Are you using a segue connected to the cell or doing a manual presentation in didSelectItemAtIndexPath? If the latter, what code do you have in that method. – rdelmar Jul 22 '14 at 15:21
  • @rdelmar: You're right. I created a test app and saw the same behaviour as you. I am presenting through the didSelectItemAtIndexPath method. I try to update my question. – Darren Jul 24 '14 at 14:53
  • 1
    Are you reloading the data when you come back to the controller with the collection view? – rdelmar Jul 24 '14 at 17:50
  • No, and in fact I'm sure that the contentOffset is reset before coming back to the viewController, as I check it in the viewDidDisappear method. – Darren Jul 24 '14 at 22:24
  • http://stackoverflow.com/a/18730399/3802077, as mentioned in a few of these answers; `self.automaticallyAdjustsScrollViewInsets = NO;` could work for you – user3802077 Jul 25 '14 at 15:24
  • Thanks, I tried that an it didn't work for me. – Darren Jul 25 '14 at 15:32
  • I don't think you can get a good answer to this question without showing a lot more of your code. There's something going on in this particular app that you couldn't reproduce in a test app, so the few lines you show aren't giving us enough information. If you could post the app somewhere or email it to me, I'd be glad to take a look at it. – rdelmar Jul 26 '14 at 05:39

3 Answers3

0

There are 2 options. If your application works with UINavigationController, it should keep the last accessed cell, not sure about how you have worked with. If not, you can always create a notification and in the moment you are getting back to the previous screen, send the update of the UICollectionView or whatever you have and scroll to the correct position. Bear in mind, the UIViewController life cycle and how it´s going to appear before to update the user interface.

AlfuryDB
  • 289
  • 1
  • 4
  • I am not using a UINavigationController in this situation as I am presenting the 2nd view controller modally. I still have access to the selected cell, but how would that give me the exact content offset of the collection view? A notification will not help, I can already use the viewWillAppear method to set my contentOffset. The issue is trying to prevent my contentOffset from being reset in the first place. Thanks for the ideas though. – Darren Jul 18 '14 at 20:16
0

You can create a CGPoint object in AppDelegate. Then you can set that value to your CollectionView objects contentOffset while present and dismiss like that;

[self presentViewController:secondVC animated:YES completion:{
    appDelegate.tempContentValue = _collectionView.contentOffset;
}];

[self dismissViewControllerAnimated:YES completion:{
    UIViewController *first = [UIViewController alloc] init];
    [first.collectionView setContentOffset:appDelegate.tempContentValue animated:YES];
}];
Kemal Can Kaynak
  • 1,533
  • 13
  • 24
  • 1-A UIViewController has no collectionView property so this will not compile 2-Replacing it with a subclass that does have a collectionView, the code in the dismiss method will do nothing as you're instantiating a controller that then gets released almost immediately 3-The appDelegate should not be used to store contentOffsets of random VCs. 4-The question is how to prevent the offset from being reset in the first place. Not trying to be rude, just trying to provide some helpful feedback. Thanks for trying to help. – Darren Jul 25 '14 at 22:01
0
   @property (nonatomic,assign) CGPoint newContentOffset;

Then when you navigate to another View / present another view

  self.newContentOffset = self.collectionView.contentOffset;

In viewWillAppear

  [self.collectionView reloadData];

   if (self.newContentOffset) {
        [self performSelector:@selector(setContentOffset) withObject:nil afterDelay:0.1];
   }


  -(void)setContentOffset {
        [self.collectionView setContentOffset:self.newContentOffset];

   }

There will be a small jerk while applying this . But if thats ok, you can go ahead with this method

Wodjefer
  • 325
  • 2
  • 6
  • 19