Implementing UICollectionView cell for items with variable number of subviews - ios

Problem
I have a UICollectionView initialised from code and I register a custom class for its cells. The custom class has a few UIStackViews to lay out a bunch of UILabels and UIViews.
One of the arranged subviews should contain a variable number of UIViews. To make this less abstract, let’s think of them as “seats" that will display faces of users attending this event (can be up to four, can be none)
Solutions that come to mind
(I’m a novice)
Solution 1
Have the custom class lay out all the "seat" UIViews so I can treat them as placeholders;
Have the UICollectionView’s cellForItemAt method iterate over the data source and unhide the “seats” that have been filled
Solution 2
Make sure that the UIStackView in the custom class can be referenced from UICollectionView’s cellForItemAt method
From cellForItemAt use addArrangedSubview to add all the needed “seats”
Solution 3
Register 5 different classes (zero “seats” to “four seats”)
Dequeue each one as dictated by the data source
This one seems to me like the least dignified, but might be the one with least performance penalty
I'm perfectly aware that there could be more, and better, solutions. So, what would be the optimal way of implementing this variable number of UIViews, and why?
EDIT:
While I think that the layout of the cell here is irrelevant, it's been requested that I post it
so here it is...

I propose Solution 3, as it will be much more performant.
Also, I have two advices:
Avoid using UIStackView, as it has slow layout performance (it is based on AutoLayout). Also, try to avoid AutoLayout in UITableViewCell and UICollectionViewCell for better performance. Here are some of the most popular and powerful open source layout libraries PinLayout, LayoutKit.
You can write base UICollectionViewCell, move all of the relevant logic there, and then just make all the needed subclasses with minimal logic overriding.

Related

UITableView vs UICollectionView vs UIScrollView?

When should I use which, and what are the disadvantages or disadvantages of each? I'm mainly confused with scrollview vs collectionview, I know tableview is limited to one column (I heard it gets messy when more than one column), but scrollview difference with collectionview seem the same to me.
Both CollectionView & TableView are basically subclasses of UIScrollView.But as compared to UIScrollView here you are provided with proper methods to provide your dataSource & delegates to handle operations user performs on data. Along with this you are provided predefined layout classes.
Now to choose between them completely depends on your UI Requirements. Suppose you want to display just a list of items with a simple UI go with TableView.If you want a custom Layout like a grid or like the one you see in Apple's photo's app CollectionView is the choice.
if you have a complex UI & you have no idea about Custom CollectionView layout classes go with scrollView.
Consider UITableView and UICollectionView first and if you cannot achieve the effect you want with them, try UIScrollView then. UIScrollView is more basic class. UITableView and UICollectionView have more delegate method for us.
If you want a list,UITableView would be better. And if you want a multicolumn,use UICollectionView.

Using UICollectionView with nested sections (stacking headers)

I'm porting my web app to iOS using Swift 4, and I need to display a list which contains multiple nested "sections" where each section has its own header.
My instinct was to use UICollectionFlowLayout, but quickly discovered that it is limited to a depth of one. Diving further, figuring I would just have to create a custom layout, I see that the IOCollectionViewDataSource protocol actually assumes a depth of one.
I suspect I can find a way to flatten the data and reproduce the illusion of nested sections, but I'm baffled that I can't find an obvious way to have UICollectionView build what seems like a pretty common interface element. Perhaps I'm missing something?
Is there a common way for accomplishing this in UIKit?
Why not use a nested UICollectionView with your custom flowlayout, if you want UI like the way you shared in the question?
The idea would be,
UICollectionView (top)-> DataSource = [Headers: [dataSourceBelowTop]]
UICollectionView (inner) -> DataSource = dataSourceBelowTop
Take the example of the above case:
DataSourceTop is = ["Mission Gorge": ["Middle Earth": [SomeCustomModel]]]
The first task would be to build the top level UICollectionView, and then each collectionView will have another collection view. Now for Scrolling, you will need to play with the flowLayout which can be explained in another thread.

Convert Complex UITableView to UICollectionView

I currently have a prototyped UITableView in my storyboard, which has many cell with very complex layout. Now, I need to convert it into a UICollectionView, because I always have some problem with the way UITableView handles cell layout(See my this question). I figured the code part to be the easy one, as I only need to tweak the inheritance of my cell classes, as well as switch the delegate and datasource with previously written code. However, I am a little stuck on the storyboard side, that is, given all my cells are complex in layout and even copying and pasting them from one cell to another would require many layout tweaking and IBOutlet/IBAction reconnecting. Is there a fast way to convert those UITableViewCells designed in storyboard into UICollectionViewCells?
I think, you save data into one class, In CollectionView, You get data from class. You remember, tableview and collection are reverse about cell and row.

UITableView && UICollectionView in one controller?

I'm trying to implement iPhone and iPad versions gracefully. They're essentially the same controller, but one the iPhone presents in a single column tableView and the iPad in a multi-column collectionView.
Here are the options I thought of:
One ViewController that asks for a different DataSource and different Delegate for tableView vs collectionView. I haven't thought this option all the way through. It does seem like it might get overly complicated.
One baseViewController and then 2 subclasses, one with a tableView and one with a collectionView. Similar to option #1 but using subclasses. Option #1 is cleaner, but this would be easier to implement.
Just use a collectionView for both, but use different UICollectionViewFlowLayouts. This was the last option I thought of and seems like by far the best option, but I'm wondering if there's a reason why #1 or #2 might be better.
So I ended up going with 1 UICollectionView, and IMO it works great.
I had to write conditionals for only 3 parts:
Returning different collectionViewFlowLayouts
Returning different sizes for collectionView:layout:sizeForItemAtIndexPath:
Different layouts for layoutSubviews of the UICollectionViewCell
Being able to use the same UICollectionViewCell was a really big plus since I am implementing a number of buttons within the cell, and I didn't have to replicate delegates for exactly similar logic in a UICollectionViewCell AND a UITableViewCell.

Does it gravely affect performance to use a bunch of different classes for UITableViewCells?

I have a bunch of different UITableViewCell types. Performance-wise, would it be better to separate them into different classes, or to have one central class and change around some attributes and views programmatically?
The reason I ask is because in cellForRowAtIndexPath you dequeue your cell, and if you dequeue a bunch of different classes, wouldn't that make reuse difficult as there would be a massive divide of classes in the reusable "pool" of cells?
You should create a class for each UITableViewCell type that you have. That's best practice for a number of reasons, including, but not limited to:
1) Modularity of code (You can modify each cell easily when the need arises)
2) Simplicity (Having one class for multiple different types of cells would be a headache with all the if/else statements etc...
3) There won't be any memory issues
Why won't there be memory issues or as you describe, "a massive divide of classes"? The UITableView will only allocate as many cells as it needs to fill the tableview when it appears. As you scroll, the cells that were allocated at first, are now queued for reuse. If an instance arises where the cell can be reused, it will be, thereby avoiding another allocation, and thereby avoiding a UI slowdown. So, at any one time, regardless of how many UITableViewCell classes you have (unless you have thousands), there will be relatively few cells in the queue waiting to be reused.
To add to user1840001's excellent answer (voted) :
You should use different classes when your cell STRUCTURE varies in any non-trivial way.
Use the same cell class if you have the same structure (set of fields) but different content to display in that structure.
EDIT: Looks like my up-vote didn't "take." NOW I upvoted #user1840001's answer...

Resources