Choppy/Laggy scrolling of Collection View with Dynamic Content - ios

I am having a problem where my collection view scrolling becomes very choppy/laggy as I get more and more cells. The screen contains a list of messages and comments for the messages, so every single view is dynamically sized. I have a bunch of custom layout attributes which I apply to handle laying and sizing everything.
I apply the custom attributes to the cells by overriding applyLayoutAttributes: and then calculate all the subviews frames from those.
I already cache the calculated sizes of cells but it is not enough.
I assume that there are some techniques people use to address this problem, like caching layout attributes, or somehow preventing the need to layout a cells subviews everytime cellForRow is called?
I assume this is a common problem since it is a problem I have faced with literally every table I make with dynamic content? I would appreciate any ideas :)
P.S. Rasterizing the cells doesn't help.

Related

How can I place a view between cells in collectionView?

I want to place a view between cells in a collectionView. Like an ad. to be added dynamically after they see the first 3 cells. Is there a method to do that?
If you could figure out a way to do that you still shouldn't. A collection view owns the area it draws in. It's in charge of placing cells where they belong within it's content view, and you are supposed to keep out.
That said, collection views are extremely flexible and you could design your collection view to display a set of "normal" cells, an ad cell, and then more normal cells. If your ad cells are different sizes or need to be spaced differently than your normal cells then you might have to create a custom collection view layout.
No, you can't. But you can add a UICollectionViewCell which will contain advertisements or something else you want to be added. It is really simple. Just create two prototype cell. First cell will contain your data, second one will contain some extra data.

Dynamic cell height issue with UITableViewCell autolayout jerk while scrolling

I am trying to do something like loading up different type of cells with custom height in a uitableview. The tableview cells are subclassed and consists of labels with the respective constraints. Each cell is having a dynamic height.
Now even before my table reloads the data, I am calculating the height that is required for the resizing of the cells and caching it in my model class so that I dont have to calculate the height when the data is rendered on the device.
To calculate height i did use the tutorial from Ray Wenderlich and I am having the right set of heights applies to the objects.
Now the problem comes. Whenever I am dequeueing the cells there is a
kind of a small jerk that gives me an indication that my cell is
dequeued while scrolling.
How can i make these movement smooth so that there is no jerk while scrolling the view ?
The height is getting assigned in and does get the value as per the current type of data getting loaded.
estimatedRowForIndexPath
Also I am calling layoutIfNeeded from my cellForAtindexPath
Suggestions are most welcome.
It's very hard to say without seeing your code in cellForRowAtIndexPath, and without seeing your cells and their respective code. Here are some general questions I would investigate:
What is the content of the cells and how complex is the view hierarchy in the cell?
Even though you are supplying the correct estimated height, an autolayout pass still needs to happen, and a complex view hierarchy will take time to resolve
Does the cell contain images?
Images that need to be decompressed from a file (UIImage imageNamed:) can be intensive and cause scrolling issues, check images are not bigger than they need to be. If needed, bump this work onto a background thread.
Are you calling a complex method to configure the cell for display in cellForRowAtIndexPath?
Look at the work actually being done in cellForRowAtIndexPath, is there a complex method being triggered in you cell subclass or view model?
Are you adding and removing views to the cell view hierarchy in cellForRowAtIndexPath?
If views are being added, removed, created, inflated from a xib, constrained etc during the cell config, this could slow things down. Try to do only what is strictly needed. Check if there is any code being run internally in the cell subclass during cellForRowAtIndexPath that could be moved to cells initWith... or awakeFromNib methods (ie code that could just run once when the cell is created, rather than every time the cell is displayed)
Also run the Instruments time profiler, see if that offers any more clues

Is there a "self.tableView.estimatedRowHeight"like method for collection cells?

I'm trying to make self resizing cells for my collection view. Ill display text parts and those text parts have many sizes, since every cell will have a paragraph. Reading a guide on appcoda and useyourloaf i got the solution to make it with table view, so the only thing i can't do on the collection view cell is this
self.tableView.estimatedRowHeight
for obvious reasons I can't use it on collection view. Is there any similar thing that I can do for collectionView cells?
PS: I can't change the collection for a tableView.
PS2: I'm using swift
In theory there is; Apple has been claiming since WWDC 2014 that there are self-sizing collection view cells in exactly the same way as for self-sizing table view cells.
But in fact every time I try this feature, my app crashes. So in my view the answer is: no, if you want dynamically sized collection view cells you will have to size them dynamically yourself. This is not difficult, however. Just implement collectionView:layout:sizeForItemAtIndexPath: and set the size of the item. If you want it to be based on internal constraints, call systemLayoutSizeFittingSize: here.

Custom UITableViewCell's subviews using auto layout - no xibs, all in code

Custom UITableViewCell's subviews added in code using auto layout works (verified). However the whole point of doing this was to not have to calculate the height of each tableview cell and the delegate method heightForRowAtIndexPath expects a height while drawing the tableview.
How can I figure out this height based on content using the auto-layout (visual format language based addition in code already added and working) and return it to this heightForRowAtIndexPath?
Also I'm I can't really do this on a background thread (or can I?) and therefore if I have a UITableView using this backed by a list of say 1000 records, this will take forever, is that right?
Autolayout in this case just means that you don't need to calculate the frame sizes of your subviews within each cell. It's got nothing to do with the heightForRowAtIndexPath method - this is used by the table view to define the cell's frame, which will then inform the layout of the subviews.
Using Autolayout to determine the heights would likely be pretty slow, and you can't do it on a background thread. If you have 1000 rows then I'd consider a hierarchical structure instead of a single table as that will be pretty tedious to scroll through. You could also consider calculating the heights at the point of setting or creating the data.
You may be able to set up an offscreen view using your constraints, populate it with your data for each item, then record and cache the height. However you'd have to do this at the data end rather than in the height method, as it would be far too slow.

iOS UITableViewCell with scrollView with dynamic content

I am trying to create a table view, in which the table view cells contain a scroll view. The scroll view can contain one or two pages of one image view each. Note that the scroll view will only scroll horizontally, so it will not interfere with the Table View's scroll view that will scroll vertically. Depending on the content, I want the scroll view to be updated with these image views, and set the scroll view content size according to responses I receive from a server, instructing the application what images to display.
In order to do that, I initially thought of creating a custom UITableViewCell subclass, and do all my initialisation of the views inside that.
However, I am just thinking about performance and memory. I know that iOS automatically deallocates already seen views and cells, when it needs to, and that it reuses the old cells when it tries to display something new (by using a reuse identifier). However, each cell will contain a scroll view with content size and subviews that will change in each cell. I want to use a reuse identifier to ensure maximum performance.
Can anyone point me in a way in which I can set up the reuse of a cell like this, and change the contents of each scroll view successfully?
Thanks.
you can make the reuseIdentifier dynamic
e.g. "cell_with_1","cell_with_2","cell_with_x" where x is the number of images
that way equal cells can be reused when sensible (e.g. when the number of images in the view is the same): 'worst case' is no reusing and a tad overhead for trying but in general I'd deem it beneficial :)
*the allocation deallocation and the basic adding of the subviews is expensive.. changing frames or images seems reasonable to me

Resources