I have a UICollectionView inside a UIViewController. The collectionView holds an array of 8 identifiers of view controllers from the storyboard. Each view controller in the array inherited from the UIViewController that holds the collectionView.
Here is the code:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return _contentPageRestorationIDs.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
BaseContentViewController *contentViewController = (BaseContentViewController *)[self.storyboard instantiateViewControllerWithIdentifier:self.contentPageRestorationIDs[indexPath.row]];
// Set any data needed by the VC here
contentViewController.rootViewController = self;
contentViewController.view.frame = cell.bounds;
[cell addSubview:contentViewController.view];
return cell;
}
So my problem is that my collection view swipe performance is really slow. How can i improve the UICollectionView's performance? Are my view controllers inside the cell are "killed" when they are not on display?
Edit:
after the advice here i have changed my array to holding a view controllers instead of identifiers nsstring.
In the ViewDidLoad:
_collectionView.delegate=self;
_collectionView.dataSource=self;
PRzeroVC *zeroVC = [[PRzeroVC alloc]init];
PRoneVC *oneVC = [[PRoneVC alloc]init];
PRtwoVC *twoVC = [[PRtwoVC alloc]init];
PRthreeVC *threeVC = [[PRthreeVC alloc]init];
PRfourVC *fourVC = [[PRfourVC alloc]init];
PRfiveVC *fiveVC = [[PRfiveVC alloc]init];
_base = [[BaseContentViewController alloc]init];
_pages = [[NSArray alloc]initWithObjects:zeroVC,oneVC,twoVC,threeVC,fourVC,fiveVC, nil];
[_collectionView reloadData];
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = (UICollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
_base = (BaseContentViewController *)_pages[indexPath.row];
_base.rootViewController = self;
_base.view.frame = cell.bounds;
[cell addSubview:_base.view];
return cell;
}
My cell is not displaying the view Any idea why?
I was able to obtain smooth-scrolling performance of a collection of cells containing each its own child view controller by using a queue to keep and reuse a set number of instances.
GitHub lists a number of reuse queue implementations; and, after a fairly thorough review of almost every one if them, I can confidently recommend this one:
https://github.com/acoomans/ACReuseQueue
Per the ReadMe: A reuse queue is a way to quickly reuse objects when object allocation and initialization is time-consuming.
The reason your view is not showing is because you're not instantiating the child view controller from within the cell subclass, and not adding the view from within the cellForItemAtIndexPath. It's about scope, and you've got it backwards.
The perfect set of instructions for adding a child view controllers to cells is provided here:
http://khanlou.com/2015/04/view-controllers-in-cells/
From the documentation of instantiateViewControllerWithIdentifier:
-
This method creates a new instance of the specified view controller each time you call it
You would be better to store an array of UIViewController
s so they can be re-used, rather than storing the IDs and instantiating a new view controller every time tableView:cellForItemAtIndexPath:
is called.
Also, since UICollectionViewCell
s are re-used, it's not wise to keep adding subviews to the cell every time tableView:cellForItemAtIndexPath:
is called. Instead, consider creating your own UICollectionViewCell
subclass with a mainView property. You could override setMainView:
to remove the old mainView from its superview, before setting the new one's frame (or adding layout constraints) and adding it as a subview.
Also you should implement the methods for proper UIViewController containment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With