How to create iflix home page layout - swift

Hi guys, please give me an idea how to create a list similar to the homepage of iflix (image attached below). I tried using table view with collection view inside the cell, but I don't like the performance because it flickers when I scroll because of the reloading of collection view cell.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: CustomCell = self.tableView.dequeueReusableCell(withIdentifier: "Cell") as! Cell
cell.bind(data: self.datas[indexPath.row])
cell.collectionView.reloadData()
cell.delegate = self
return cell
}
When I removed the cell.collectionView.reloadData() the scrolling is smooth but the displaying of data is incorrect because cells are reusing.
Can anyone give me a better idea on how to implement a layout like this? Thank you in advance.

there could be a variety of reasons why you are experiencing flickering, in fact the first release of that ViewController had the same issue on older devices. I would recommend first Analysing your app using the Time profiler to investigate the cause of the flickering you are experiencing. It’s very likely, as we discovered there there is not one main cause but a collection of smaller issues that when added together on the main thread causes the flickering. Below I will detail a brief description of how we manage to reduce the flickering effect.
The ViewController contains one vertical collection view, each row is its own cell that owns a horizontal collection view.
One thing we try to ensure is that drawing a cell is as efficient as possible. All cells and views are configured via ViewModels which for our case is a PODO (property only data object).
The ViewModels can be easily preprocessed on a background thread and contain e.g url, titles, hide/show buttons, cell sizes etc for any orientation. Plus it makes it very easy to test. We ensure that all images are the correct size so there is no time required to scale the image, along with that each visual item is opaque and rasterised to the correct screen scale. We also found for our code that if each cell uses ‘preferredLayoutAttributesFitting’ that can help to reduce the flicker also.
The next part is to try to help reduce the amount of effort taken to when calling reloadData. If each cell in the row is the same size then using UICollectionViewDataSource can be more process intensive than setting the item size, instead you can set the itemSize in the xib/storybaord or use a UICollectionViewFlowLayout. Before a cell is shown to the user the methods “collectionView cellForItemAt” and “collectionView willDisplay” will be called, you can try and split cell configuration work over those two method calls.
I hope that helps.

Related

How to add Activity indicator to end of UICollectionView

Hi I have been trying to add an Activity Indicator, or a Loading spinner, to the bottom of my collection view. I have searched online on how to do so but there is not a clear way to do so.
I do not want to use a cell for the indicator itself because my cells a pretty big. (2 cells take up the whole screen.) So I would just like to have a small loading spinner at the bottom for when users scroll down.
Through the research that I have done I have seen that some people use this function below and a separate class to build the spinner.
private func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath) -> UICollectionReusableView{}
But I do not know how to use it. I already created a class called LoadingViewController() but in all honesty don't know if it is event he right type. Currenlty I have it set as a UICollectionReusableView
For a little more background, I already added the ability paginate data. So when I scroll down the collection view, new cells are loaded. Now the problem is I want to show a little spinner at the bottom when the data is loading because if not the app stutters and looks like it is broken.
Or is there a better way to show load items in a collection view that does not cause the scroll to freeze?
Please let me know if you have any questions regarding my situation I'll try to answer them to the best of my ability.

UITableView Cells Expand With A Delay

I am making a to do list app and have 3 custom cell types. For task cells, it is just an imageview on the left and a textview on the right. I would like the cell to automatically resize itself when the textview text is to large for a single line.
I have added the correct constraints and have added this to viewWillAppear
tableView.estimatedRowHeight = 30
tableView.rowHeight = UITableView.automaticDimension
However, when going into the view with the tableview, the cells remain small for a second and then expand to their correct size. Also, when initially adding the task, the cell doesn't resize unless either going back and opening the view controller again or the tableview is scrolled up until the cell is out of view and then letting go.
This is very odd behaviour and even happens when removing the two lines above from viewWillAppear. It just happens for no reason.
I would like the cells to be of the right size when going into the view and not resizing a second later.
An example of what this looks like is below
Okay so I finally found the answer. I made my cell programmatically with auto layout and some of that was setup in the layoutSubviews() method inside the cell. This method is only called when needed. So when scrolling up or down.
To fix this, in your cellForRowAt method, just call
cell.layoutSubviews()

Segmented controller

UIView,SegmentedController & UIContainerView in a ScrollView or something similar?
In my storyboard I have a VC containing a UIView at the top, segmented controller in the middle & 2 ContainerViewControllers at the bottom with embeded segue's to new VC's.
In the new VC's I have a TableView & a CollectionView (For example, the Instagram profile).
My issue is that I need the SegmentedController and UIView to scroll with the ContainerView(TableView/CollectionView), at the moment only the ContainerView part scrolls and the parts above that are fixed.
Now I'm guessing I probably need to put everything into a UIScrollView, so I tried that & placed all the costraints correctly. But when It came to configuring it in the Swift file, I only really now how to set the height of the scroll but oviously the height I need can vary and isn't a fixed height!
If anyone can help me here that would be fantastic, or maybe point me towards a similar question already asked here? I have already looked, but did not find anything unfortunately!
Here's an image below explaining basically what I'm after, if above I wasn't very clear..
here is an example you can see: https://github.com/Jackksun/ScrollIssue
the image is here, as I dont have enough reputation I cannot place it in the post!
You can use only UITableViewController. You will define three custom cells and in cellForRowAtIndexPath ask for the Index number, if it is 0 you will set the elements in that cell accordingly
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: TableViewCell!
// stuff in UIView
if indexPath.row == 0 { set the cell here}
// for UISegmentedController
if indexPath.row == 1 { set the cell here}
// cells that will repeat
if indexPath.row >= 2 { set the cell here}
return cell
}
Update1
Define how many custom cells you will use in Attribute inspector for tableView, you will see them instantly in Storyboard
Update 3
Did you mean this? It is completely table view with 4 custom cells. I didnt use Collection view at all but I think it works as you wanted

Can't focus UICollectionViewCell inside UITableViewCell

so I am exploring the new tvOS. As I wanted to kind of replicate the horizontal feature section of the app store (e.g. "Best New Apps")
My plan was to use a UITableView to lay out the base structure (rows) and use an UICollectionView for all the individual horizontally scrollable items.
Unfortunately the tvOS always focuses the UITableViewCell, not the UICollectionViewCell inside. I've already read about the
override var preferredFocusedView: UIView? {
return aView
}
So using this inside my controller is kind of hard regarding getting the correct subview.
Is there anything I could look into or could someone please point me in the right direction? Iterating through all subviews until I get the correct one seems like a bad idea.
Thanks a lot!
I tried out a similar situation where I had a CollectionView within a CollectionView to get the setup you described. Let's call them innerCV and outerCV. To get innerCV to be focused and not outerCV's cells, I set this delegate method to return false for outerCV.
- (BOOL)collectionView:(UICollectionView *)collectionView canFocusItemAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
In turn, innerCV's cells are now focusable as opposed to outerCV's cells.
Credit for this goes to Apple. I used their sample project as a guide to start. Check out the Focus samples within their project.
Sample Project: Apple tvOS UIKitCatalog
I used a different approach..
Setting the tableview selection property to No Selection in storyboard makes the focus engine to focus on UICollectionViewCell cell rather than UITableViewCell.
Hope it helps :)
Image

CellForRowAtIndexPath returning the wrong cell

I am running into an issue where cellForRowAtIndexPath is returning the wrong cell and therefore, it is seguing and performing other actions on the wrong cell.
I have built custom cells that are quite big because I am fitting some UIImageViews (+text +buttons), so a cell takes up the entire screen. When you scroll down and two cells are on the screen at the same time, if you tap on the top one, it segues to the content of the bottom one (same for button actions inside the cell).
I thought this might be specific to IB, so I rebuilt everything in code, but am still having the same behavior.
Is there any way to fix this and maintain the correct indexPaths?
I think you have your perspective wrong. cellForRowAtIndexPath doesn't return wrong cells. It should just return a fresh cell, which may have been recycled if you're using dequeueReusableCellWithIdentifier or similar. In which case, dequeueReusableCellWithIdentifier will return any old cell which may have just scrolled off the top. It's your job to take the fresh cell (which may be a new cell or a recycled one) and stuff the correct values in it, inside cellForRowAtIndexPath. Then the cell it returns will be the "correct" one because you've just written all the correct values to it. So I would look at your implementation of cellForRowAtIndexPath to make sure that correct values for the index path that you're passed are stuffed into the cell that cellForRowAtIndexPath returns.