Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

contentOffset not updated on UICollectionView if scrollToItemAtIndexPath is called inside viewWillAppear

Tags:

I have a UICollectionView that is used to simulate the new calendar in iOS 7. This collection view is inside a controller that has a selectedDate property. Whenever the selectedDate property is set the collection view should scroll to the date in the collection view.

The calendar controller's viewWillAppear also ensure the selected date is visible because this controller is cached and reused.

-(void)viewWillAppear:(BOOL)animated {     [super viewWillAppear:animated];      [self.calendarView scrollToDate:[self selectedDate] animated:NO]; } 

The problem is that the VERY first time the calendar controller is shown the scroll does not work. The contentOffset of the collection view is not updated.

My current workaround is to schedule the scroll to occur on the next run loop using

dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^(void) {         // Scroll to the date.     }); 

It looks like when the UICollectionView is not in a window you cannot scroll. Scheduling the scroll to happen on the next run loop ensure that the view has been added to the window and can be properly scrolled.

Has anyone else experienced this issue and what their workarounds?

like image 600
Reid Main Avatar asked Oct 01 '13 16:10

Reid Main


2 Answers

If you are using auto layout, the issue may be that the constraints haven't set the frames yet. Try calling the scrollToDate: method in viewDidLayoutSubviews (without dispatch_after).

@interface CustomViewController ()  @property (nonatomic) BOOL isFirstTimeViewDidLayoutSubviews; // variable name could be re-factored  @property (nonatomic, weak) IBOutlet UIScrollView *scrollView;  @end  @implementation CustomViewController  - (void)viewDidLoad {     [super viewDidLoad];      self.isFirstTimeViewDidLayoutSubviews = YES; }  - (void)viewDidLayoutSubviews {     // only after layoutSubviews executes for subviews, do constraints and frames agree (WWDC 2012 video "Best Practices for Mastering Auto Layout")      if (self.isFirstTimeViewDidLayoutSubviews) {          // execute geometry-related code...          // good place to set scroll view's content offset, if its subviews are added dynamically (in code)          self.isFirstTimeViewDidLayoutSubviews = NO;     } 
like image 123
bilobatum Avatar answered Sep 23 '22 08:09

bilobatum


you can always force auto-layout to layout.

override func viewWillAppear(animated: Bool) {     super.viewWillAppear(animated)     self.view.layoutIfNeeded()     self.collectionView.scrollToItemAtIndexPath...... } 
like image 43
maxpower Avatar answered Sep 22 '22 08:09

maxpower