Embedding UIViewcontrollers inside UICollectionviewCells - ios

In my app I have a home page which has a Card/Grid Layout with multiple section. So UICollectionView is the obvious choice here. But these cards vary a lot in design, loading data and their functionality too. So putting all those in one single controller would be cumbersome, complex and hard to maintain. So we thought we need to separate these out into their own UIViewControllers. Each handles a type of card and calculates its contentSize to be shown inside a card. Our main home page controller is only responsible for putting those viewcontroller views inside the UICollectionView cells.
To summerize,
A HomeViewController which has a CollectionView
Every view inside the collectionViewCell and its data are maintained by its own controller Class.
All the instances of the controller are inside the HomeViewController and added as its children.- Apple Guide
The appearance calls to all the children viewControllers are made by ourselves since, the contentSize (Which is used as the item size for the collectionView layout) calculation of the controller views need the view to be loaded and data to be set.
My question is this, is this design choice right? Or what approach would you chose to implement such a screen? Since we create a lot of viewControllers (one for every cell), does this affect memory or performance? And If I want to cache only some viewControllers or load them as the user scrolls or when its time to add it to the collectionView cell, how do I go about it as calculating the size of that cell depends upon the data and the views while laying out the CollectionView layout.

I think your approach is valid and from a theoretical standpoint it makes sense to separate a view from its data. But, in this case I would prefer to have the UICollectionViewCell subclass implement its own data, basically acting as a viewController. This will simplify your code a bit since you don't need the added viewControllers and the code that comes with them; instead you can simply add your tableView to the cell's contentView. This seems more natural to me, as then you can have HomeViewController's collectionView automatically handle calling its delegates when cells are moved offscreen and on, and during the loading process. You won't need to send messages to cells about who they are or when they should load, this will all be taken care of for you automatically. Also, I really don't think having the view lifecycle methods on each cell is valuable, and is less intuitive than having a cell load and refresh as part of a collectionView. Either way works, good luck!

Related

Using TableView instead of ScrollView

For creating a login page or something like that, in autolayout case I use tableView instead of using a scrollView in viewController. For IndexPath majority cases I reuse the customCell. For entirely different items only I use another customCell. Since the Cell Class are increasing in my project. I dont know is it a good practice. Please share your opinion to increase the overall performance and least memory usage for my application.
Putting UITableView in all views is not a good practice every time.
I recommend using scrollviews and content views inside them in pages like login.
Use Tableviews only in those screens which show repeated contents.
I have seen codes generated through tableview controllers in every page.
I dont do in that way.
Better you go for Scrollviews.. Its a good method as far as I have seen.

How to fix smooth scrolling issues in a UITableView with custom view controllers in headers?

I have created a tableview in such a way that all the rows are of 0 height but with custom headers. I am displaying different view controllers in different headers. I am able to parse the table properly but when I scroll down, it doesn't scroll smoothly.
The view controllers I added in the headers are mostly collection view and page view controllers, which display images.
What can I do to fix this issue?
Thanks in advance!
This is really tough without any code, but understand these principles of a UITableView:
Every time you show a cell or header that includes a view controller or view that hasn't been instantiated, it creates that on the main thread which is also doing the scrolling, hence the lag time.
UICollectionViewControllers and UIPageViewController are EXTREMELY heavy classes that take a lot of time to instantiate and setup. I would recommend NOT putting them in a UITableView unless you have to and if you do, make sure you're only instantiating one of them per cell and not recreating them each time.
Loading images can also take quite some time if not done asynchronously, especially depending on where you're getting them from. Offload as much as you can onto separate threads.

Custom cells into a scroll view vs. using Table View

I have a list like Facebook's news feed,There are so much news from my users and I have to show them like Facebook does.
First I create an NSObject class for generating each cell's object. Then I create a UIViewController that is initialized with this object class. This controller is each object's cell.
-(id)initWithNewsObject:(NewsObject *)new Delegate:(id)delegate{
self=[super init];
if(self)
{
_delegate=delegate;
_new=[[NewsObject alloc]initWithNewsObject:new];
}
return self;}
So I create the news list using for loop in my main View Controller.
Here is my question,Which one of list structure ensures the best performance ? Listing the cells with for loop or using TableView ?
Hands down Table View.
Table view will show/hide/recreate cells only when it needs and from device to device, it will handle those automagically. If you even attempt to do this for your own ScrollView, you will have to cater for different device sizes and resolutions and orientations.
If you don't do this for your own ScrollView, you will have a lot of views just sitting in the memory, not a very good choice.
And even if you do all these successfully, congratulations, you have just reinvented the wheel, you have just created your own MyTableView instead of UITableView.
Tableview will be MUCH better since you don't have to manually manage scrollView's content size and especially if you don't need any pinch to zoom or horizontal panning support. Tableview also has some nifty lazy loading built in so you don't have to manage the memory for all of the objects you load on the screen as well.
I think using a tableView with variable cell sizes or custom cells is definitely the way to go.
Table View.
Imagine that users continue scrolling for hundreds of your "cells." You'll have to manually manage the memory for hundreds of view controllers vs. iOS handling them via the dequeue method in table view.
It automatically recycles cells for you and you can make the content size different based on what type of cell it is (image, text, video, etc).

Tips for how to code a very complicated custom UITableViewCell

Please see my mockup pictured above. I am a bit puzzled as how to code this. I guess I would use one UITableView and have all customizations on one cell. Any other ideas? I wasn't sure if it would be better to have multiple tableviews on one controller or something instead.
First off, this design really won't work except on iPad. It's just too much to try to cram onto an iPhone screen.
Collection views are like a more flexible form of table view. You can arrange collection views in rows, columns, rows AND columns, circles, or whatever you want.
You can make a collection view act like a table view, but it's more work, and a little more confusing.
If your UI is a vertical list of cells, a table view might still be a better fit, since it matches what you're doing.
Assuming this app is iPad only:
Create a custom subclass of UITableViewCell, with it's own XIB file. Define the contents as desired. Making each "tile" (the 5 boxes shown in each cell) in the table view cell a separate custom subclass of UIView might make sense, or it might not, depending on how you expect to use them. If they are always in the same order, and never used anywhere else but in this table view, then no. Just build the cell from components. If you ever think you might use one of these tiles somewhere else, or if you might ever display them in a different order, then yes, make each tile a separate custom UIView subclass, and use those custom views in constructing your cell.
Having multiple UITableView is bad idea – when you scroll one of them others will remain static. I would recommend you to use one table view but decouple a cell in the separate views (or even view controllers) and have a special view (maybe with .xib) for each of 5 components.

UIPageViewController: how to have "negative" spacing between view controllers (with scroll-transition style)

I have to implement a view controller (on iPhone, portrait only, full screen view) where the upper part of the view must have an horinzontal, paged scrolling behavior, potentially infinite.
I already used for similar purposes UIPageViewControllers, to take advantage of the datasource and delegate protocols, which are very helpul for manage memory and other stuff (keeping only 3 view controllers in memory, providing delegates to handle actions exactly when a transition is done and so on): so I think that in this case too this component is the best choice.
But here comes my problem. In the view I'm realizing, I have to let the user understand that he can swipe left and right to move to another view: a page control is not a good choice, since the scroll could be potentially infinite, so I would like to let a small portion of the views of the left and right view controllers to be visible.
Something like that:
link to the image (sorry I cannot include images in my posts yet)
Up to now I have not been able to figure out how to realize this. In the options during initialization, UIPageViewControllerOptionSpineLocationKey can be specified to set (from documentation) "Space between pages, in points": but this seems to work only with positive value, so that the space increases, while it ignores negative values that could reduce the space.
I hope there might be a solution using page view controllers, since at the same time I need to refresh a table view in the lower part of the screen when a transition is complete, and the delegate method of page controllers is ideal for this aim.
Maybe a collection view can be an alternate solution, but it is more complicated and I'm not sure how to obtain a behavior like the one I described to refresh the table view.
If needed I can attach some code and a screenshot of the prototype
Ok, I understand that this is not possible and why it is.
The datasource methods load, when needed, the view controllers that are before and after the current one. Making these view controllers' views always visible, as I desired, will require that the datasource loads more than one view controllers after (or before, depends on the direction of scrolling) the current one, to be ready for the pan actions (potentially, before the animation is ended by the user lifting up its finger, two view controllers "after" or "before" could become visible it my desired configuration), and this is not intended by UIPageViewController on iPhone, especially in portrait mode.
So actually, the only way to achieve that more than one view is visible in an horizontal-scrolling component at any time, is to implement a UIScrollview with horizontal paging and calculate the contentSize and other sizes accordingly.

Resources