I have this very nice collectionview that loads pictures from my server. Now, if the pictures are loading slowly, the collectionview is actually scrollable, but if the pictures are loading fast, instead, the collectionview is basically frozen until all the cells are finally loaded.
I'm pretty sure this is something related to the fact that I'm using dispatch_async to update the ui (inserting cells and sections), so I'm wondering if there's a way to update the ui that still allows me to scroll the collectionview while the items are being added.
Is there anything I'm missing?
Thanks in advance for your help!
The easiest way to solve this issue is to use SDWebImage an UIImageView alternative , and call the sd_setImageWithURL:placeholderImage: method from the tableView:cellForRowAtIndexPath: UITableViewDataSource method. Everything will be handled for you, from async downloads to caching management.
You can find it here: https://github.com/rs/SDWebImage
So remove any dispatch_async, set right away the number of cells on this method:
- (NSInteger)numberOfItemsInSection:(NSInteger)section;
Scroll performance is going to be good with this tool
Related
It's a technical question, or about good practices...
I have this App, its a social network, where we have the timeline. In this timeline I have to render a lot of cells on a tableview which I have done this way:
create a Cell (with header, body and footer) -xib file
in this cell I have a method: setupCell() - which configures the contents
for each kind of post I instantiate a correctly view(xib) on body of this cell (like PhotoPost, TextPost or VideoPost etc) and configure constraint to set the size of views.
Also, I'm using:
tableView.estimatedRowHeight = 603
tableView.rowHeight = UITableViewAutomaticDimension
And kingfisher to download images asynchronous.
And, what is best way: storyboard, xib, or code?
So, my problem is that my scroll is lagging - I'm using reusable cells, but every time that tableview delegate calls cellForRow, I have to setupCell().
My first idea:
I get the post array with a task then a create cells for each post and append this to an array of cells, so when cellForRow is called I just get the right cell from this array.. It make better. But still not enough(I'm testing on a iPhone 5c).
My next ideia is create different cell for each kind of post, and save a variable for this cell of his size to setup on heighForCell method.
You think that looks good solution? Can anyone give me an opinion and suggestion? I'am very tankful in advance..
After experimenting with possible solutions I decided to use AsyncDisplayKit to solve my problem, it offers great smooth scrolling.
http://asyncdisplaykit.org
It's complete SDK and has well written documentation so was easy to implement. I would recommend it if you are struggling with a similar issue to me.
I already found entries with that topic on this page and also a website that provides a tutorial for that problem. But nothing worked very well.
The tutorial sad I should double the height of my tableView so cells loaded earlier, but with a higher tableView I never reached the last cells.
My problem is, I use a tableView to display my apps mainpage. This mainPage shows every time a topic and if its necessary for that topic it shows for example a cell with a map, one with pictures and sometimes not. Problem now, if I trying to scroll to my view its always lagging because it loads a map or this pictures. And scrolling back again because the loaded cells already deleted. I used a tableView because of the possibility to switch celltypes(mapCell, pictureCell, textCell) on and off.
I understand this feature, because of memory issues but in my case its not that much and it would be better if all my cells be preloaded and stay in memory until I change the topic.
Is there a swifty way to told my tableView to have this behavior?
Thanks a lot and nice greetings
I would suggest a different approach. Set up your table view controller to install placeholder images in your cells, trigger an async download that you cache to disk, and then update the cell with it's downloaded content if it's still visible when the download is finished.
There are various third party frameworks that do all this housekeeping for you.
Declare a cell array.
Follow these steps whenever change in your topic.
Clear you array
Create and configure all cells add to your array.
Return these cells to datasource methods using row index. Don't use tableview dequeue method here.
I have a UITableView in my application. When the table is scrolled almost to the end, I download more data and reload the table.
If the tableView was scrolling, at the time I call [tableView reloadData]; scrolling stops. How can I achieve effect of not stopping the scroll meanwhile reloadData? I think I need to somehow save scrolling speed and then restore it, but how to do this?
P.D. I really searched this question before asking.
I thing, this method (insertRowsAtIndexPaths:withRowAnimation:) is the key.
There is a use case and a nice tip described on SO: the use case and the tip.
Since UITableView is subclass of UIScrollView, you can use UIScrollViewDelegate's scrollViewWillEndDragging:withVelocity:targetContentOffset:
method to determine how far it is supposed to scroll and then after table reload call setContentOffset:animated: with that target offset (or beginning/ending of tableview if it becomes smaller) to simulate continued scrolling
EDIT: since your targetContentOffset is probably going to be CGRectZero, you will have to recalculate it somehow using velocity from the same method
if i am not wrong you are looking for a function call Lazy load. I can recommend you to search SVPullToRefresh
here!
I have a Uitableview in which i am loading custom uitableviewcells
and all that cells are calling a class which draw a collectionview
with scroll in it depending on amount of data,
so I'have seen that when I scroll then my UITableview take a jam on
those cells which are adopting scrollview then after a very narrow
second everything is fine but when I scroll again then it again
happen
I know that the problem is I am drawing cells on each time but I have
also take a look by initiating an array of views and then pass the
specific view to the cell on run time but strangely it got more stuck
when I am doing this.
Kindly help me on this
My Approach in your scenario would be to create “Section Header” and “Section Footer” for UICollectionView like the approach in this tutorial http://www.appcoda.com/supplementary-view-uicollectionview-flow-layout/ which i feel much simpler and easy to implement.
I have a uitableview that loads fairly large images in each cell and the cell heights vary depending on the size of the image. Scrolling performance is decent, but can sometimes be jerky.
I found these tips I found on the FieryRobot blog:
glassy-scrolling-with-uitableview
more-glassy-scrolling-with-uitableview
Does anyone have any tips for improving uitableview scrolling performance?
Cache the height of the rows (the table view can request this frequently)
Create a least-recently-used cache for the images used in the table (and invalidate all the inactive entries when you receive a memory warning)
Draw everything in the UITableViewCell's drawRect: if possible avoid subviews at all costs (or if you require the standard accessibility functionality, the content view's drawRect:)
Make your UITableViewCell's layer opaque (same goes for the content view if you have one)
Use the reusableCellIdentifier functionality as recommended by the UITableView examples/documentation
Avoid gradients/complicated graphical effects that aren't pre-baked into UIImages
If you are subclassing
UITableViewCell, don't use a Nib,
write it in code instead. It's much
faster than loading Nib files.
If you're using images, make sure
you're caching them so you don't
have to load from file more than
once for each (if you have the
memory -- you'd be surprised how
much space images take up).
Make as many elements opaque as
possible. Similarly, try not and use
images with transparency.
The developer behind Tweetie has written extensively about this and has some code that demonstrates how it was done for that app. Basically, he/she advocates one custom view per table cell, and drawing it manually (rather than subviewing with Interface Builder, among other options).
fast-scrolling-in-tweetie-with-uitableview
Also, Apple has updated its own sample code for TableView in its TableViewSuite tutorials (maybe in response to this?)
TableViewSuite
#1 performance killer for UITableView scrolling is drawing shadows on any cell view layer, so if scrolling performance matters then don't do shadows unless basically it doesn't slow down your main thread.
thought this had to be said since none of the accepted answers made mention of shadows and layers. :+)
Any problem with UITableView scrolling performance can be solved using techniques already described in other answers. However many a times sluggish performance is caused by something inherently erroneous, or repetitive.
The fact that UITableView reuses the cells, and the fact that each cell may need its own image - together makes the solution bit complex. From how it's being solved the general way, here I summarize things that should be taken care of:
Load data into data source - from REST / database. This step should be done on background, eventually using dispatch_async along with GCD queue.
Create and initialize relevant data model objects and putting them inside an array
[tableView reloaddata]
Inside cellForRowAtIndexPath, include code that will set data (text) from correct data model object of the array.
Now images maybe in the form of URL too, so this step might be little quirky because of cell reuse done by table view. The heart of the fact is to load once again image from device cache / URL using async queue, then set it to correct cell.image (whatever is your cell image property).
To avoid problems, refer to this tutorial about lazy loading of images inside table view.