Bug in UITableView ( deleteSections:withRowAnimation: )? - iphone

I have problems using this UITableView method:
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
First the documentation says:
animation:
YES to animate the deletion of sections, otherwise NO.
But the parameter animation is actually of type enum UITableViewRowAnimation, not BOOL!?
So how can I disable the animation? I've tried NO and UITableViewRowAnimationNone. Nothing works. The section deletion is always animated.
I know that I can use [tableView reloadData] instead. That would solve my issue. I'm just curious if that is a known problem and if it is possible to disable animation with this tableview method.
Thanks!

It's kind of a hack but this gets rid of the insert animation:
[UIView setAnimationsEnabled:NO];
[self.tableView insertRowsAtIndexPaths:insertedIndexPaths withRowAnimation:UITableViewRowAnimationNone];
[UIView setAnimationsEnabled:YES];

About the YES/NO in the doc whereas the parameter is of type UITableViewRowAnimation, I guess this is a rest from an old version of the API where the parameter was a BOOL before. Anyway, the documentation is indeed wrong.
Don't hesitate to send a feedback to Apple for this (using the "It's good but…" link at the bottom of the doc)

Well, obviously the documentation is indeed buggy. The parameter you pass says how you animate the deletion. If you pass UITableViewRowAnimationNone, the update happens instantly without animation. However, when you have a section below the one you delete, it will move upwards in an animated way.
You should try to make use of the animations. This way a user can see what happens.

I believe you need to embed the deleteSections call inside a beginUpdates block:
[tableView beginUpdates];
[tableView deleteSections:... withRowAnimation:... ];
[tableView endUpdates];
The documentation seems to say this anyway. I haven't tested this with UITableRowViewAnimationNone though.

Related

Getting NSIndexPath of a row for UISwitch

I have a tableview with custom UITableViewCells, each row in the table has a UILabel, UISwitch and detail disclosure indicator.
I'm looking for the best method of capturing the UIControlEventChanged for the switch but I also need the NSIndexPath of the switch that changed to update Core Data.
I don't want the UISwitch as an accessory type either.
I've been googling this for hours and the solution that keeps popping up is to use
[switch addTarget:self action:#selector(switchTapped:) forControlEvents:UIControlEventChanged];
then in the switchTapped: method use the following to get the NSIndexPath
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];
Is there a better way of doing this? I already have UITableViewCell subclassed, can I put a method in this class to return the NSIndexPath for a given switch?
Thanks in advance for any help
I'll take another opportunity to link to my answer here - tags and view hierarchy walking are clunky, error prone and unnecessary, and I see them recommended all over the place in SO answers. You can find the index path of any control using its frame and the table view's indexPathForRowAtPoint: method.
Setting a proper tag for the switch in each row of the table is a feasible solution. Set the tag according to the indexpath of the row in which it is present.
That way you avoid the possible problems that might arise to changes in view hierarchy.
This post might also help you.

TableView's viewWillAppear() called but data is not refreshed

Sometimes tiny looking problem is ignored to handle in the last but you never know that will become nightmare for you, happening with me.
Thanks in advance, problem my app's settings page contains tableView and every setting element is one of the view. One of the setting item (row) offers show expands a few list of items in another listTableView. After making a selection in listTableView when i come back to my settings tableView using navigationItem.leftButton (Back), selected item value overlaps the previous item's value, in the sense [tableView reloadData] in viewWillAppear works fine but tableView rows are not fresh drawn. It doesn't refresh the cell's UI.
Note that if settingTableView has any subview like UIButton etc it has the latest value, i can use that as workaround but the only problem is when is select this row again Selection has old value that overlaps new value on selecting the row.
I will appreciate any suggestion or sample code using will be great help.
Thanks a ton
Amit Singh
Use [tableView reloadData]; in your viewWillAppear method.
or use [tableView reloadData]; in viewDidAppear method
The problem you are facing is perhaps due to portion of cell that is reusable and the one that is not reused. Check out the code you are writing inside the block of
if(cell==nil){}
components you have created inside block will not get recreated and others might be recreating causing the overlapping on the cell.
In my case, I had to use [self.tableView reloadData]; rather than [tableView reloadData]; in the viewWillAppear method.

TTTableViewController scrollsToTop not working

I'm using a basic Three20 TTTableViewController subclass which employs its own datasource and model.
The problem is that I cannot seem to use the scrollsToTop property of the table. This is a standard property for the table, inherited from UIScrollView and very commonly used.
I have tried all of the following, in numerous different locations/methods within my class:
self.tableView.scrollsToTop = YES;
[self.tableView setScrollsToTop:YES]
I have also tried overriding the method
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
return YES;
}
All without success.
NB. To be clear, I am referring to the standard gesture of tapping on the status bar to scroll a visible table view to the top (i.e. first row).
Any help much appreciated!
There is some confusion
According to Apple documentation of UIScrollView :
scrollsToTop
A Boolean value that controls whether the scroll-to-top gesture is effective
This is just to tell scrollview that taping status bar will make view scroll to top.
What you are looking for is this UITableView method :
scrollToRowAtIndexPath:atScrollPosition:animated:
Scrolls the receiver until a row identified by index path is at a particular location on the screen.
With three20
Since you are using three20 what you want to do can be easily done thanks to its UITableView+Additions.h > - (void)scrollToFirstRow:(BOOL)animated
[self.tableView scrollToFirstRow:YES];
Without three20
If not using three20, here is how three20 does:
- (void)scrollToFirstRow:(BOOL)animated {
if ([self numberOfSections] > 0 && [self numberOfRowsInSection:0] > 0) {
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop
animated:NO];
}
}
Another way to do this
I think that would also work (untested), using UIScrollView directly, (extracted from three20 too):
- (void)scrollToTop:(BOOL)animated {
[self setContentOffset:CGPointMake(0,0) animated:animated];
}
or :
[self.tableView setContentOffset:CGPointMake(0,0) animated:YES];
Thanks to Vincent G for pointing me in the right direction. It appears that the issue is to do with what code is called in the class's init and viewDidLoad methods.
I discovered that under the following conditions, two tableviews are added as subviews of the view controller's view:
Making reference to the property tableView in the viewDidLoad method, e.g. [[self tableView] setTableHeaderView:]
Building the dataSource of the table within the init / initWithStyle method.
With two UIScrollViews present, the scroll-to-top action does not work properly, as Vincent pointed out. I will file these findings as a bug with the Three20 guys but by following these steps it can at least be avoided for now.
Edit: It seems that this maybe due to the viewDidLoad method being called BEFORE the init in some cases. If reference is made to the tableview in the viewDidLoad, before it has been created, I think the class is creating one. The init will then make another one.
try this:
self.tableview.scrollingEnabled=YES;
self.tableview.scrollsToTop=YES;
Also check that your delegate is returning YES in this method:
scrollViewWillScrollToTop:
As #imnk suggested, my thoughts as an answer, even though I don't have a real solution.
What I'm experiencing (and just verified to be sure) is, that once I change the frame property of the tableView, the touch on the statusBar doesn't work anymore...
According to the Apples documentation on UIScrollViewDelegate, every scrollView's delegate (regardless of its size) can return YES on - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView.
But I looked through three20 and changed it in my implemetations of delegates, but with no success.

How to auto-scroll UITableView?

I am trying to do something interesting.
I am pulling some JSON data and populating cells in a UITableView. How can I make the UITableView scroll ever second or so? I want to give the effect that as new data is coming in, the table is scrolling, so it is streaming.
Any ideas?
Yes, use scrollToRowAtIndexPath:atScrollPosition:animated:.
You could also use UIScrollView's scrollRectToVisible:animated: if you want to have more finegrained control and can calculate exactly what your scroll position should be in pixels. (UITableView is subclass of UIScrollView.)
But if you are just adding cells, sounds like you could also just use insertRowsAtIndexPaths:withRowAnimation:, this is also "interesting."
Just do this
[table reloadData];
NSIndexPath *myIP = [NSIndexPath indexPathForRow:[arrayIn count]-1 inSection:0] ;
[table scrollToRowAtIndexPath:myIP atScrollPosition:NULL animated:YES];
in anywhere where arrayIn is your array by which your table populate.
you can use uitableviews scrollToRowAtIndexPath to do this....heres a link reference
You can call this method whenever as youd like to scroll your tableview
And you can call performSelector:withObject:afterDelay: for the timer effect - although if you are really pulling in data every second, it's best to just reloadData as you go.

UISegmentControl and UITableViewController animation

How can I animate my "removal of tableviewitems" when the user changes between segments in the UISegmentControl?
The behaviour should be similar to "Missed/All" calls in the Phone App.
The deleteRowsAtIndexPaths:withRowAnimation: and insertRowsAtIndexPaths:withRowAnimation: will provide the animation for you.
If you need to perform a more complex operation (inserts and deletes), you start a block. similar to a UIView animation block:
[tableView beginUpdates];
//add and delete
[tableView endUpdates];
Bear in mind you will need to update the model to reflect the changes in the table.
UITableView can be sent a message: deleteRowsAtIndexPaths:withRowAnimation:
The withRowAnimation argument determines the type of animatio that will be used in removing the cell.
I don't know if any of those animations match the missed/all functionality exactly though. If they don't, I'm guessing you will have to set up an animation to collapse the height of the cells before removing them.