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.
Related
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.
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.
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.
I have a inherited UITableViewCell class from which I create a custom cell containing a UITextField.
The UITextField is 25 pixel height by default.
The behavior I want is that when the user clicks in the textField, the UITextField should change to 100 pixel height and the cell should grow accordingly.
I can detect when the UITextField receive focus thanks to notifications and observers but I wonder how to programmatically make that tableView:HeightForCellAtindexPath: be called.
Like Endemic says, tableView:heightForCellAtIndexPath: is the method you need to implement. According to Apple, the most efficient way to trigger a resize is an empty beginUpdates / endUpdates block, like this.
[tableView beginUpdates];
[tableView endUpdates];
It saves you the overhead of reloading the cell contents and, I believe, gives you a nice animation you wouldn't otherwise get from reloadData.
You must have a link between the cell and the table view controller. Since you are already creating your custom cell in your controller the easiest way would be to use the delegate pattern.
#class CustomTableViewCell;
#protocol CustomTableViewCellDelegate
- (void)customTableViewCellDidEnterTextMode:(CustomTableViewCell *)cell;
#end
#protocol (nonatomic, assign) id<CustomTableViewCellDelegate> delegate;
and just call the delegate method where you are detecting when the text field gets focus
[self.delegate customTableViewCellDidEnterTextMode:self];
and in the controller
- (void)customTableViewCellDidEnterTextMode:(CustomTableViewCell *)cell {
self.editingIndexPath = [self.tableView indexPathForCell:cell];
// from Jablair's answer
[tableView beginUpdates];
[tableView endUpdates];
}
And then in tableView:heightForCellAtIndexPath: just return your special height for self.editingIndexPath.
You would probably have to include another delegate method to know when focus is leaving the text field as well.
Another approach would be to use notifications but that will just complicate your code and if there is only one receiver of the message a delegate is the preferred way. A third approach would be to set the delegate of the text field to your controller instead of to your cell.
The bottom line, you need to provide the link between the cell and table view your self and I believe using a delegate pattern is the best approach.
The tableView:heightForCellAtIndexPath: method is called whenever the table view loads data, so simply calling reloadData (or one of the other, more selective reload methods) on the table view should work fine.
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.