UIViewController within UICollectionView

2019-02-03 03:03发布

问题:

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?

回答1:

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.



回答2:

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.



回答3:

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.