views:

910

answers:

4

I am making a UITableView with a UISegmented control ala the Recent Calls tab in the Phone app.

The first segment will be all items, the next 2 will be subsets of the full list of items.

I created 3 arrays which hold the 3 different lists of data.

My first solution was a wholesale swap of the data and the a reload:

[self setData:newData];
[self.tableView reloadData];

This works great with the exception of animation, there are no indicators that the data has indeed changed. I could add some sort of indicator message, but I would rather use the method employed by the phone app, an "accordion" effect collapsing deleted cells and expanding added cells.

To accomplish this, you cannot just swap out the data (or can you?). It doesn't trigger animation. The only means I see is to do this is manually delete and add cells from the backing model. So what is an efficient algorithm for accomplishing this? My first guess:

I have a multidimensional array to represent sections of cells.

  1. create an array to hold the index paths of cells to be added
  2. iterate through each section of the NEW data
  3. check if the section of the NEW data has the same count as the OLD data
  4. if not, iterate over each item in the NEW data
  5. If the item is also in the OLD data, do nothing
  6. If the item is not in the OLD data, add index path of item to array of cells to be added
  7. repeat for each item in section
  8. repeat for each section in NEW data
  9. create an array to hold the index paths of cells to be deleted
  10. iterate through each section of the OLD data
  11. check if the section of the NEW data has the same count as the OLD data
  12. if not, iterate over each item in the OLD data
  13. If the item is also in the NEW data, do nothing
  14. If the item is not in the NEW data, add index path of item to array of cells to be deleted
  15. repeat for each item in section
  16. repeat for each section in OLD data

then call the apprpriate UITableView methods:

- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation

This algorithm seems like has lots of room for improvement. Has anyone tackled this problem yet? How did you implement it?

Thanks for any input

A: 

It looks to be way more complicated than it needs to be. UITableViews work on a 'pull' basis -- that is, instead of pushing the data onto a table, it calls your data source delegate and pulls the data into it.

Given that, each time you call reloadData you can swap out and return anything you want. All you have to do is use the segmented control actions to change an index value that chooses which data array is the 'current' one to use when the table asks for a cell's value.

Now as far as animating the change is concerned, there are a number of ways you could have the same effect. If you really want to do the accordion effect you'll have to manage a lot of state for tracking whether you're in display or table switch mode, etc. A much easier way would be to have an overlay view that you could animate in and out to visually indicate the change. Then in the animation view's completion handler you would call the reloadData.

Ramin
You method makes sense, except as you said for the accordion effect. Otherwise it is easy. I already have it implemented with no animation, I just wanted to be pretty... I did consider the overlay, but was just trying to make the app use "standard" behaviors.
Corey Floyd
A: 

Hi Ramin,

Even I would like to achieve this accordion effect on UITableView much on the similar lines as mentioned in the post. Any idea on how to implement this?

I tried to think of some way but all the ideas looked very complicated and I am not confident on implementing this idea. Any help on this would be greatly appreciated.

A: 

Hi guys

Did any one have any luck animating the filtering? I have exactly the same scenario; a segmented control with an 'all' and 'filtered' option.

I've looked at Corey's suggested approach for tackling this but am struggling to translate this to actual code.

Any suggestions or examples for rolling this one onward?

Edit:

Actually, something that had just occured to me - could chaning the height of the cells that I wish to hide provide the same animated effect? Is this even possible after the cells have been drawn?

Phil Patch
check these: http://iphonedevelopment.blogspot.com/2010/03/my-last-word-on-nsfetchedresultscontrol.htmlhttp://iphonedevelopment.blogspot.com/2009/11/using-kvo-for-table-updates.html
Corey Floyd