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

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.

Related

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.

UITableView cells with both UIActivityIndicator & UIProgressView

I have a UITableView that contains several cells and some of them (the ones for files that are still uploading) have both an UIActivityIndicator and an UIProgressView. The ones for files that are finished use a different icon (instead of the activity indicator) and hide the progressview.
This table is using a NSFetchedResultsController as data source, so I get the updates on the data model and update the content.
Everything works just fine. The problem, however, is performance. Every time I call reloadData my UIActivityIndicators flicker, and it's not very smooth. Although I'm caching from the nib file, reloadData will have to calculate the new progress % for the ProgressView and I don't do anything with the ActivityIndicator other than hiding it if upload is complete.
Anybody ever tried something similar? Is there a workaround?
I was thinking about having an array of my progressview references and use that instead of calling reloadData.. not sure if this is the correct approach.
Thanks,
Fernando
When you call reloadData on the UITableView, all the cells of the table view are completely refreshed, re-assembled and redrawn. All the old ones are thrown away. This means that all the subviews of the UITableViewCells are removed and re-created too (including your UIActivityIndicator and UIProgressView). The refresh causes these views to flicker, or perhaps jump back to their start state. As there is no way of setting the frame of a UIActivityIndicator, your suggestion of restoring some progress value simply isn't possible.
Instead, perhaps you should try and engineer your "refresh" to not require a complete refresh of the table? For example, if you want to change the text of a UITextField within the view, you could simply access this text field and set the text property (no refresh is required). Or, if you want to hide your progress indicators, you could go into the appropriate object instances and set their property. You should design your app so that this is possible. Making changes this way avoids having to reload cells from scratch.
Besides the benefit of fixing your problem, using this method of updating, you should also see a large performance increase. reloadData is a very costly method to use and should be only used if it is absolutely necessary to really re-create the entire UITableView from scratch.
Hope this helps. :)

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.

How do I create a TableView like in network Settings App on the iphone?

How do i make such a Table view? So if I turn on the switch, 2 cells should be added.
I've already tried
[tableView numberForRowsInSection:6];
[tableView reloadData];
but this doesn't work as expected :(
any ideas?
The best thing would be 2 sections the first section contains 5 cells, the second section contains one cell with a switch turned off and if the Switch has changed 2 cells will be added to section 2.(Added with an animation :))
mhh..
Thanks in advance, I'm very excited on every answer :)
Where did you pull this -numberForRowsInSection: method from? As far as I (and the documentation) know, it doesn't exist and has never existed as a method of UITableView. Guessing is going to get you nowhere, much less inventing methods from thin air.
Perhaps you should review some tutorials that cover the basics of using UITableView before you attempt this. I doubt someone is going to take the time to write you a full class to do this and put it in an answer, and you'll be much better off in the long run if you don't simply try to copy/paste code that you don't understand. There exists much documentation and examples that cover UITableView, and that's just considering what's available from Apple - UITableView is such a frequently used class that searching Google for something like "UITableView tutorial" is going to give you pages and pages of results.
I will give you a quick overview of what you would need to do, though:
1. Of course, you can start with the UITableViewController template in Xcode and start customizing it to fit your requirements...two sections, however many rows per section, etc, determining that based on some model-level objects if necessary.
You'll need to either create a custom UITableViewCell subclass or customize the default UITableViewCell layout a good bit (at least by adding a UISwitch subview) when you create new cell objects in tableView:cellForRowAtIndexPath:.
The UISwitch should be configured to send a message to your view controller when the switch's value changes using -[UIControl addTarget:action:forControlEvents:] for the UIControlEventValueChanged event.
In your implementation of the action method for this switch value change, you'll need to implement logic to determine whether rows should be added or subtracted, and then actually add or subtract the rows. You can use beginUpdates/endUpdates, insertRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation: to have the nice smooth row animation behavior instead of simply calling reloadData.

Reordering UITableView sections on the iPhone by dragging (like reordering rows)

Is there anything currently in the SDK that allows for re-ordering of tableView sections? As in, move the entire section below or above an adjacent section? This is plausible with individual UITableViewCells. Haven't seen it done for sections though.
Maybe not ideal but fairly simple so worth considering:
Add Up/Down buttons to your section headers. Down on the first, Up on the last and Up and Down on all the others. Then respond to the button presses by programmatically re-ordering the table. Up moves the section up one and Down moves the section down one.
Martin
There's no built-in touch-responsive API for moving table view sections - you'd have to do it programmatically then send a [tableView reloadData] message or similar.
It is concievable, though, that you create a table view where each UITableViewCell's view is itself a UITableView containing a section of your data, so that the cells in the "master" table are draggable as UITableViewCells. This would let you reorder "sections" in your table, but they wouldn't be sections anymore - they'd be separate tables, each with a single section.
Maybe as an alternative idea, reloadData on the table to only show the sections as a kind of "collapsed all" view on your table (maybe it is possible to even animate this?) which then has one section, containing all sections as row elements. The only extra required would then be a button that will set your table to this state.
I tried to move rows from one section to another, while updating the datasource of course. But this seemed to be mission impossible. Empty cells in between, wrong contents in sections, wrong ordering of sections were the only results I got.