UIViewController within UICollectionView
Asked Answered
G

3

20

I have a full-screen UICollectionView in my app. It scrolls horizontally and each cell fills the collection view's bounds. The collection view is managed by a UIViewController.

Given that each "page" is reasonably complex, it makes sense for each page itself to be managed by an associated UIViewController. iOS 5 has support for view controller containment, so that the child controllers should receive the appropriate lifecycle methods (e.g. viewWillAppear:, etc) when views are attached and detached. How nicely would this play with view recycling?

Scrolling from page "1", to "2", a new view would be created (as both could be onscreen at the same time during the touch-down). Moving from page "2" to "3", the UICollectionView could successfully dequeue the view for page "1", but what happens now? Would I forcefully insert the view into view controller three like so?

id cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ident" forIndexPath:indexPath];
UIViewController *child_controller = [self controllerAtIndexPath:indexPath];
[child_controller setView:cell];
// ... and so on

This feels wrong. However, I can't think of a correct way to reuse views correctly in this instance. Am I taking the wrong approach entirely?

Gramps answered 20/6, 2013 at 3:48 Comment(1)
If each cell fills the collection view's bounds, why not just use a UIPageViewController with its transitionStyle set to UIPageViewControllerTransitionStyleScroll? It's designed to host one child view controller per page.Mortify
W
8

I don't think that UICollectionView is the best choose for your task.
Like rob mayoff said: you can use UIPageViewController.
Another option can be using UIScrollView with 3 subviews (previous, current, next). And you will be able to easy manage it's position and scroll view offset to achieve effect that you want.
This is described in WWDC 2011 'Advanced Scrollview Techniques'. You can grab source code from there.

Welsh answered 29/6, 2013 at 21:19 Comment(3)
I completely agree with Sergey: this task is what UIPageViewController created for.Coalesce
@Sergey Kuryanov ,I am in same situation but Facing issues of memory in UIPageViewController ,any help you can provide to solve memory issues .I am using arcHomologize
Maybe you are trying to save too many VC at the same time. It's hard to detect problem without actual code.Welsh
T
7

I've done the same thing, but with two view controllers visible at once, and reorderable, so a collection view was the right choice.

It turned out that removing the previous view controller's view and adding a new one caused quite a performance hit on scrolling, with removing the view being the slowest method.

Reuse of cells only makes sense if the new use of the cell is similar, but different - e.g. you're changing the text of a label or putting a different image in an image view. If you're ripping out and replacing the whole view hierarchy, you're not really reusing the cell.

What I ended up doing was using new cells for each view controller that could be contained. In my case there was a limit on the number of cells meaning that there wasn't really a problem with memory consumption having that many view controllers in play at once.

So, in a nutshell - don't reuse cells. It's more expensive than keeping the old ones around. Scrolling down a hundred row table is different to scrolling across a few full screen views. But, given the fact yours are full screen, a scroll view might be a better option.

Testator answered 29/6, 2013 at 21:47 Comment(8)
I'm doing the exact same thing right now (the edges of other vc's visible, a la the app store search results). Any other problems you ran into or pointers?Mccary
The only thing I found useful was to have all the child view controllers adopt a protocol which allowed the collection view's controller to tell them when they were moving on and off screen - and in there, you'd do the viewDidAppear / disappear stuff, which otherwise wouldn't get called, because the views only appeared once.Testator
Did you end up using paging to force them to the next item? Trying to decide if .pagingEnabled is best of targetContentOffsetForProposedContentOffset.Mccary
The customer wanted to "fling" the scrolling so I couldn't do paging, had to implement my own snapping. They wanted it to feel like paging, but with the ability to scroll past multiple items.if you can, use paging, it's much simpler.Testator
Looks like you can't really use paging when you have multiple visible, because you don't want it to page the entire frame. And you can't shrink the frame and use clipsToBounds=NO because Collection view gets rid of the cells that aren't within the frame.Mccary
It seems it's forcing me to use the deque method to make new collection view cells so they have a reuse identifier. How did you get around that?Mccary
I registered multiple reuse identifiers with the same cell class, e.g. cell0, cell1, and created the reuse identifier based on the index path.Testator
Looks like you HAVE to use a nib to create your own cell that you don't want to dequeue. #13282131Mccary
J
6

It's probably better to use UIView subclasses (or UICollectionViewCell subclasses) instead of encapsulated UIViewControllers. The encapsulated UIViewControllers have to have knowledge of their parent view controller, which could cause problems with code maintainability.

Complexity doesn't automatically mean you should look at adopting UIViewController. UIViews can be quite complex as well. The role of a UIViewController is really to provide additional encapsulation and lifecycle that it doesn't sound like you need here.

As other's have said, UIPageViewController seems like a good alternative too, but I don't know the specifics of your situation.

Jamey answered 3/7, 2013 at 23:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.