I have this button on my view, and when I press it I insert a new section in my table view ( I have a logical condition in my
-(NSInteger) numberOfSectionsInTableView:(UITableView*)tableView
{
if (slide==TRUE) return 2;
return 1;
}
And also in my -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
. My section is added as it should, but I have read somewhere that this can be animated, because when I press my button the section is added but with no animation. I think I should use this -(void)insertSections:(NSIndexSet*)sections withRowanimation(UITableViewRowAnimation) animation
but I haven't found a proper example on the web.
Manipulating rows and sections into UITableView using animation is made pretty easy using the following API's (emphasis on the last two):
insertRowsAtIndexPaths:withRowAnimation:
insertSections:withRowAnimation:
deleteRowsAtIndexPaths:withRowAnimation:
deleteSections:withRowAnimation:
beginUpdates
endUpdates
You should update your data model anywhere between the beginUpdates
and endUpdates
methods. It doesn't matter if you update your data model before or after insertion or deletion methods just so long as you do it between the beginUpdates
and endUpdates
methods.
When adding a new section using the insertSections:withRowAnimation:
method, you do not need to call insertRowsAtIndexPaths:withRowAnimation:
to add rows into it. The insertRowsAtIndexPaths:withRowAnimation:
method is just for animating an existing section changing. Similarly, you do not need to call deleteRowsAtIndexPaths:withRowAnimation:
when you remove a section using deleteSections:withRowAnimation:
.
I generally do these in separate beginUpdates:
endUpdates
calls, however you can insert and delete at the same time. Just be aware that the UITableView will first try to delete rows / sections and then try to insert them regardless of the order you do it in your code.
Discussion part of deleteRowsAtIndexPaths:withRowAnimation:
Note the behavior of this method when it is called in an animation block defined by the beginUpdates and endUpdates methods. UITableView defers any insertions of rows or sections until after it has handled the deletions of rows or sections. This happens regardless of ordering of the insertion and deletion method calls. This is unlike inserting or removing an item in a mutable array, where the operation can affect the array index used for the successive insertion or removal operation. For more on this subject, see “Batch Insertion and Deletion of Rows and Sections” in Table View Programming Guide for iOS.
int indexOfNewSection = 4; // TODO: change to meaningful value
[self.tableview beginUpdates];
[self.tableview insertSections:[NSIndexSet indexSetWithIndex:indexOfNewSection]
withRowAnimation:UITableViewRowAnimationAutomatic];
// Update data model
[self.sections insertObject:sectionObj atIndex:indexOfNewSection];
[self.tableview endUpdates];
UITableViewRowAnimation
is an enum declared at the top of UITableView.h You can also view it in the UITableView reference. It's smallish, so I'll just paste it!
typedef enum {
UITableViewRowAnimationFade,
UITableViewRowAnimationRight, // slide in from right (or out to right)
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone, // available in iOS 3.0
UITableViewRowAnimationMiddle, // available in iOS 3.2. attempts to keep cell centered in the space it will/did occupy
UITableViewRowAnimationAutomatic = 100 // available in iOS 5.0. chooses an appropriate animation style for you
} UITableViewRowAnimation;
Basically it tells the table view from which direction you want the rows/sections to be animated in/out. A little experimenting will demonstrate the effect of each.
For example, inserting a row with UITableViewRowAnimationTop
will trigger an animation which gives the impression of a row coming into the table view from a space immediately above that of its final destination in the table view.
So your insertion might look like:
-(void)sliderValueChanged:(id)slider {
slide = slider.on;
[tableView beginUpdates];
if (slider.on) {
[tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationTop];
// TODO: update data model by inserting new section
} else {
[tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationTop];
// TODO: update data model by removing approprite section
}
[tableView endUpdates];
}
And you will have to be sure that your delegate and data source provide info that is consistent with your assertion to insert sections/rows. From your question, it looks like you have done so.
EDITS:
I don't think you have to call reloadData
. UITableView
requires that your data model reflect the changes you make with with the insert/delete methods. So that, for example, if, before a call to insertSections:withRowAnimation:
(with which you are inserting a single section), your numberOfSectionsInTableView:
method returned 1, then, after the call, it must return 2. To do otherwise throws an exception. It is this enforcement of consistency that allows you (again, I think) to avoid the call to reloadData
- the necessary data is being reloaded by the whole beginUpdates:
endUpdates:
transaction, and any updates to the model you make during that transaction must match one-for-one your insert/delete calls.
Clear as mud?
UPDATES
If you were programming explicit animations, then I would say that you could do it in the 'completion handler' (or just program the animation directly for that matter), but that is not available to you here. I think you can wrap the button-presenting code in its own method in the view, then set a timer to call it after a short amount of time, say, .2 seconds (you'll have to experiment to see what looks good). e.g.
[NSTimer scheduledTimerWithTimeInterval:.2 target:self selector:@selector(presentButton) userInfo:nil repeats:NO];
That should do the trick.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With