What exactly does reloadData call? - iphone

When calling reloadData on a UITableView what methods are actually invoked?
[tableView reloadData];

The whole table view is reloaded, it calls cellForRowAtIndexPath to get the cells for all your rows and sections...doing so it also calls numberOfSections method of tableView datasource and numberOfRows method of tableview data source etc etc

Also, for future reference, that information is readily available in the documentation here. Copy/pasted 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

For the accept answer is very good. But I want to mention all the visible cells will be recreated. Usually this not a big deal. But if your tableViewCell stored property contains some data might be lost.
For example, click a button on a tableViewCell to request some data from internet and saved the retrieved data to a stored property. If you reloadData, then the retrieved data will lost. Of course this is not a proper actually make a request from tableViewCell. But just want to explain this situation.

Related

Is there any way to clear table view content widhout using reloadData

Is there any way to clear table view content without using [tableView reloadData];
No matter what you do, if you do not clear your TableView's datasource, when a user scrolls the table it will populate you the table with new/reused cells with the appropriate content. You could use the deleteRowsAtIndexPaths:withRowAnimation: TableView method but again, once the cells are removed it will attempt to populate the table with whatever is left in the datasource. So make sure you clear that out first.

Implementing "More" button in tableView without reloading the whole tableView again

I'm developing an iOS application in which i have a UITableView containing list of people coming from web-service and i have a more button on bottom. When user clicks on more it calls a service which provides some new people for the list. Now i want to add this list with the previous tableView list without reloading the whole tableView. how do i achieve this.
Any help would be really appreciable. I can provide my code of more button where i'm calling the service to get the data from service.
UITableview provides several APIs for manipulating the content. You should use the
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
method. The way how they should be applied is described in the Table View Programming Guide.
Practically, when the button is clicked, you start the network request for the list of names and when that finishes, you add the rows to the table with the above API.
Note: as long as you do only this modification to the table view, you don't have to use the beginUpdates, endUpdates methods. If there are multilple changes carried out at once (deletion, addition, reordering) then the beginUpdates/endUpdates is necessary.
Have a look at UITableView's - beginUpdates; and - endUpdates method.
In between calling these you'd have to insert the rows into the table view. If you are using UITableView's - insertRowsAtIndexPaths:withRowAnimation: method you can even skip the begin- and endUpdates.
Make sure to insert your new objects to your data source object before calling insertRowsAtIndexPaths:withRowAnimation:.
If you don;t want to reload the table then, at least, you have to call
insertRowsAtIndexPaths: withRowAnimation:
except that you can't show the newly added data in your table view.
As per my experience , It is not possible to add/display new names to table view without reloading it.
But you can achieve your task as follows ;
You can set arraCount(one varaible) for namesArray count. After calling webservice, you can increment arrayCount varaiable and reload the table view , which will display new added names in the table.
Hope this will help.

Detect jump using a UITableViewIndex

How do you know that you scrolled using the UITableViewIndex ?
I have some basic info to show on my cells, and when I jump/scroll I need to retrieve info about thoses cells by a request for a group(page) of items.
So in order to request only thoses I've stopped to, I need a way to know that I've stopped scrolling (I used scrollViewDidEndDecelerating) but with the UITableViewIndex we ca just jump to another index or scroll though them.
The only feedback that you get is in the UITAbleViewDelegate protocol - none of these report that the table view has scrolled.
However, you will get calls to tableView:cellForRowAtIndexPath: calls to your data source - this will tell you that the table view has moved enough to want a new cell.
Also, you have the visibleCells property of the UITableView itself to see where you are in the table?
It might help if you put more detail into your question - why do you need to know that a scroll has happened?
The UITableView inherits from UIScrollView so you can also implement the UIScrollViewDelegate methods such as scrollViewDidScroll. When the table view scrolls, these will be called.
However, if you explain why you need to know whether the table view has scrolled, there might be a better answer.
Edit:
From your updated question, it's still not totally clear whether you need the scrollview delegate methods.
If you just need to update the contents of the cells themselves, put that in cellForRowAtIndexPath and the table view will automatically call it when the cell comes into view.
If you need to update something outside the table view, you might still be able to do it in cellForRowAtIndexPath or you can handle scrollViewDidEndDecelerating: and then use the table view's visibleCells or indexPathsForVisibleRows methods to get the list of cells currently visible.

When is the right time to change the datasource for a UITableViewController

After rendering a UITableView with a given datasource, I want to be able to switch to a different one prior to calling reloadData.
Tried doing it in the method
- (void)viewDidAppear:(BOOL)animated;
but as far as I can see this isn't called when all the visible cells are rendered.
By placing a breakpoint it seems as if nothing is actually rendered. So I must have misunderstood its actual purpose.
Is there a API callback for that or do I have to programmatically look for it?
e.g. in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
when indexPath holds the index for the last rendered cell in the tableview.
To put it into perspective (somewhat).
Suppose we have a UITableView which has a "static" datasource. Once all the static data is displayed, you want to switch to a dynamic datasource which fetches the data off the internet and reloads each row as fetched.
So I'm actually looking for the "right hook" in which to make that change from one datasource to the other.
Are there any other issues one should be concerned about?
Further clarification. I have written all the required code (e.g. an UITableViewController with the static data initialized, different datasources, background threads for the dynamic views, a delegate to notify the UITableViewController as new data is coming in) what I haven't figured out (what the question is all about) is when to actually make the switch from one datasource to the next.
When you call reloadData it forces your UITableView to re-query your data source regardless of the amount of data that is already loaded. Also, the cells that are not visible are not being loaded, so practically the last cell is only filled with data if and when you scroll down to it. If you know for sure that all your cells are visible at once, as you might have a small number of them, you might do as you suggested and call your update function when indexPath holds the index for the last cell in the tableview.
Edit:
In the light of your edits, I'm thinking that perhaps the moment you should switch data sources depends on the state of your "live" data - when you've got enough data in it to be able to show enough of it on the screen. That is, let the static data be displayed, and only switch when you've already fetched a number of values in your live data source.
Another idea might be keeping only one mutable data source, with pre-loaded static initial data. As you fetch new "live" values, you start by replacing the ones that you already have, and then continue adding new values if their number exceeds the initial number of static entries.
viewDidAppear is all about the view controller, not the table. The table reloading will never call that method.
What you want to do, is better handled either via a delegate approach or using notifications. Set up the static data set in viewDidLoad, but then right away start the background dynamic data fetch. When that fetch is complete, have the code downloading the new data call you either as a delegate, or issue a notification your the view controller with the table listens to, and reset the table view data - then you can simply call reloadData, and the cellForRow:AtIndexPath: method will be called again for the rows on the screen (reload data will also revert back to the top of the table).
UITableView load the cells lazy, in other means it only loads the cells that are visible to the user. When the user then scrolls down, the table view will load the new cells while the "old" cells will be released. There are ways to load the entire data source, but this is not recommended from Apple - since it will be heavy on the memory load of the iPhone.
viewDidAppear() is probably your best bet.
The viewWillAppear: and viewDidAppear: methods are only called when your UIViewController gets pushed on the screen (e.g. by an UINavigationContoller or UITableViewController).
What I would do in your situation is to call a method on your own view controller when your dynamic data source is ready (or whenever you intend to change the data source). In this method set the data source and then call [[self tableView] reloadData];
What you should look out for is, if you are constructing your dynamic data source in the background (which I suppose you do) then you need to call your method on the main thread using performSelectorOnMainThread:

When should one use UITableView reloadData ? And defect associated ;)

I have built a UITableView with custom cells which each contain 5 textfields (a bit like a grid). The cells can be edited inline (no need to go in a separate view).
I am faced with some wierd defects when it comes to using reloadData.
my table footer is dynamic (calculates a value based on the cells). Should I call reloadData everytime I update a cell ? Or is there a way for the footer only to be updated?
When I start editing my cell but leave it empty (do not write any text in the textfield), the cell does not move to edit mode if I have used reloadData. Is there any known defect when doing reloadData on empty cells?
Basically I am not really sure on the best practices to use reloadData and did not find any guide anywhere. Any advice would be very much appreciated.
Regards,
Jonathan
You should minimize reloads in tableviews, and use it only when you cannot update the table other way.
For example when deleting a row you do not need a reload, just use deleteRowsAtIndexPaths or deleteSections as needed.
Other views you can just update their properties. For example if you have a label in the footer, you just need to set its text property. You do not need a table reload.
I think you cannot edit directly some properties of the cells outside cellForRowAtIndexPath method. In cases like this you will need a table reload that will call cellForRowAtIndexPath method.