UITableView does not respond normally when I scroll during loading - ios

I have come across a very tedious problem. When I try to load data asynchronously and then finally call -reloadData the tableview does not decelerate upon a scroll event and does not respond to touch events. How can I prevent this from happening ?

There is a table view with some data in it. The user is manipulating the table as new data comes in asynchronously. The proper way to modify the table is to not use reload data, but to use the "insert..." methods, which leave existing cells alone.

Related

Maintain collectionview speed after reloading data in UICollectionView

I am implementing a chat app using UICollectionView. Initially I fetch only 100 messages. As the user scrolls, I fetch some more messages and then reload the collection view. To maintain the scroll position I set the content offset but scrolling gets stopped. How to maintain the scrolling speed after reloading the UICollectionView so user doesn't feel jerk?
You could try to use the prefetchDataSource that was introduced in iOS10.
UICollectionView Prefetch Data Source in iOS 10?
There're several approaches to handle this.
You don't use reloadData() but rather insertItemsAtIndexPaths:, that way you don't have rebuild the whole table and only build the items you need.
You load additional data when use hits a specific point your collection view. In a willDisplayCell method you can check if indexPath of a cell is getting close to the last index in your data source and load additional rows. In the moment user will scroll to the last item, all the stuff will be already there so you don't have worry.
In my experience the best way is to use both of this approaches combined. Because in general using reloadData() every now and then could be very resourceful depending on your cell layouts.

Is there a way to directly access UICollectionView elements without reloading?

I have another question open where I'm trying to figure out how to reload the collectionView without auto-scrolling. I was also realizing there are a lot of other situations where I will need to change things in the collection view. Also I have some items that I will want to change the .alpha on and change the text of. Is there a way to do all of this in Swift? For example (to be specific) if I have a collection view with a view in each cell and that view has a textField in it, can I change the alpha and text, (change alpha with animation even) without reloading entire table?
Look at the documentation for UICollectionView. There are several "reload" methods:
reloadData()
reloadSections(_:)
reloadItems(at:)
If you just want to reload a single item, update your data source's data and then call reloadItems(at:) passing in the index path for the item.
Another option, if a cell is currently visible, is to use the cellForItem(at:) method to get a reference to an existing cell. Then you can directly access UI components of the cell as needed. You should also update your data model as needed so if the user scrolls and comes back, the cell will be rendered properly.
Most appropriate where you can update your custom view of a particular UIcollectionViewcell is reloadItemsAtIndexPaths.
You would be handling a particular item than whole collectionview with reloadData.
You can handle it via notifications or some call backs in your code where you can make decision when to update which cell.
Hope it will help you.

Refresh the UITableView with a complete refresh of the data

I have a view which shows a list of entries in a UITableView. The data for the list is an NSArray. When the user is on this view, there is an asynchronous call to a webservice to retrieve the latest entries. When I have downloaded the latest entries, I update the NSArray and then I send off a notification to the notification center. The UITableView is listening to this event and will try to reload the table.
But with this approach I get an error which is on the lines of "The object was mutated during reading".
After going through similar questions here on SO, I see the suggested approach is to remove objects and add objects at individual indexes and ask the table view to reload the data.
Is there a way to replace the array completely and ask the table view to reload the data ?
UITableView's reloadData method should do the trick.
From Apple's documentation:
Call this method to reload all the data that is used to construct the
table, including cells, section headers and footers, index arrays, and
so on. For efficiency, the table view redisplays only those rows that
are visible. It adjusts offsets if the table shrinks as a result of
the reload. The table view's delegate or data source calls this
method when it wants the table view to completely reload its data. It
should not be called in the methods that insert or delete rows,
especially within an animation block implemented with calls to
beginUpdates and endUpdates
https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableView_Class/index.html#//apple_ref/occ/instm/UITableView/reloadData
if you have Updated NSArray Object
Then you can use directly following method of UITableView
[tableView reloadData]

UITableView pull to refresh automatically

I got a UITableViewController and the data of the list is get from the server.
Supporting scroll down to refresh data.
My question is when view did load. I don't want user use finger to pull it down get the data, but UITableView scroll down itself automatically and get data from server.
Edit:
Sorry, my question is there is a method named pullDownToRefresh, for example. If user use finger to pull down the tableView, the function is triggered. And now, I want to make tableview pull down by itself, and trigger the function automatically.
I also need to make tableView scrolls down. I tried beginRefreshing, but the tableView is not really scrolls down.
If I understand your question correctly, you need to programatically display the refresh control(without finger swipe) and reload your tableView.
UIRefreshControl's "beginRefreshing" method serves your purpose.
Create a UIRefreshControl property in your UITableViewController
Call beginRefreshing method on that property whenever needed
call endRefereshing method when you have completed refreshing, reloading your tableView
More at this link :link

How can I make my UITableView request the X next cells that are outside the visible table?

I would like to have my UITableView load 3 or 4 cells outside of the table so that any data to be shown there is already loaded when I scroll down.
I have some images, and data that must be downloaded before it can be shown in the cell.
This causes a visible delay before the images are loaded when scrolling.
I can manually trigger loading of this data by doing it in the UITableViewDataSource tableView:cellForRowAtIndexPath: method. I've done this before, but I'm curious if there's an easier way to do it.
Is there any way to expand the reusable cell pool, or adjust how the cells are loaded/recycled?
EDIT:
To clarify, I have lazy loading of images and data in place.
Everything works fine, I just wanted an easy solution to the "prefetching" problem.
Which can be solved in many ways that has nothing to do with the view itself. Right now you can easily see the images load as you scroll. I just wanted them to load right before they become visible.
You may be looking for an asynchronous table view that loads the data asynchronously.
Apple provides a sample app demonstrating this:
LazyTableImages
Of course, you could pre-cache the data and begin downloading data into your datasource before they scroll.
The general idea is that you are loading data into a datasource (that is separate from the UI), so you can do this at any time (and in the background). You can display temporary data or some type of loading image or spinner if the data isn't loaded yet.
If data of the cell will be loaded when cel becomes visible, you can programmatically scroll the table view by scrolling to the bottom cell and go back to the first cell without animation. Another way would be creating all the cells and placing them into array when your view controller is created, and feed the table from that array that contains already created cells. I think there is no way to extend the cell pool as you are asking. Hope this helps, Good Luck!

Resources