UITableView reloadData when editing and keep animations - objective-c

I'm reloading a UITableView like this by overriding -setEditing:animated in my UITableViewController subclass when the user puts the table view into edit mode.
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self.tableView reloadData];
}
This works but is there a way to keep the animations? Normally the red delete button and move button indicators slide into view.
I'm hiding section titles for empty sections but I want to show them when editing so the user can move a table view cell into an empty section which is why I'm doing a table reload when editing.

Try -reloadSections:withRowAnimation: instead.
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
// specify appropriate sections you have.
[self.tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 1)] withRowAnimation:UITableViewRowAnimationAutomatic];
}

Related

Toggle edit button to done

Been trying to get the button to change from "edit" to "done". I am doing a tutorial and it seems to work on their end but not mine. I can't seem to find the issue.
The code:
- (IBAction)onEditButtonTapped:(UIBarButtonItem *)sender {
[self.tableView setEditing:true animated:true];
sender.style = UIBarButtonItemStyleDone;
sender.title = #"Done";
}
You are doing it the hard way. UIViewController already provides such a button.
Lets assume you want this button on the right side of the navigation bar.
In viewDidLoad, you want:
self.navigationItem.rightBarButtonItem = [self editButtonItem];
Then to handle the button, simply override the setEditing:animated: method:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
}
The button returned by the editButtonItem method is setup to call the setEditing:animated: method for you. There's no setup required.
I assume this means you have added your own table view to a UIViewController. If you are using a UITableViewController then you don't need the call to self.tableView setEditing... since it is already done for you.
If you really want to use your own button. Make sure you set the possibleTitles property of the UIBarButtonItem.

How to handle users pressing back button too quickly after pushing a viewController?

Usually after the viewController is pushed, I want to do certain things. In add phone feature, for example, I would open edit business and set the focus to the phone field.
If after viewController is pushed users press back button too quickly the app crash.
What's the standard way to do so?
This is the code:
+(BGBusinessEditViewController *) pushNewEditViewControllerWithBizandReturnValue: (Business *)biz withNavController :(UINavigationController *) nav andSelectPhone:(BOOL) selectPhoneAfterward
{
BGBusinessEditViewController * editBusiness = [[BGBusinessEditViewController alloc]init];
//[editBusiness view];//load the stuff first
[nav vPushViewController:editBusiness animated:YES andPerformBlock:^{
if (biz) {
editBusiness.biz=biz; //viewDidload must be called first before setting bizs
}
if (selectPhoneAfterward)
{
[editBusiness selectPhone];
}
}];
return editBusiness;
}
-(void) selectPhone
{
NSIndexPath * ipth =[NSIndexPath indexPathForItem:BGBusinessEditTextPhoneNumber inSection:0];
[self.tableView selectRowAtIndexPath: ipth animated:NO scrollPosition:UITableViewScrollPositionTop];
[self tableView:self.tableView didSelectRowAtIndexPath:ipth];
}
Basically I created a category in nav View Controller that will run code only when the navigation controller already reach - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
Well, Hide the back button until viewDidAppear, and then unhide it.

Strange behaviour with UITableViewController and UITextFields

I'm observing some strange behaviour when working with a UITableViewController and UITextFields in the cells.
The UITextFields delegate is set to the UITableViewController and when entering editing mode the tableview scrolls to the relevant cell, and does not obscure the input with the keyboard.
However, when I present another view controller using
[self presentViewController:vc animated:TRUE completion:^() {}];
And later dismiss it with
[self dismissViewControllerAnimated:YES completion:^{}];
The table stops scrolling and resizing to fit the keyboard.
It does not seem to matter where I call the presentViewController method (in the cell, in the headers or in a toolbar)
Any ideas?
UPDATE 1:
Delegate for my UITextField is set in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath with cell.textField.delegate = self
I only override viewWillAppear:(BOOL)animated:
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[GAI sharedInstance].defaultTracker sendView:#"Some view name"];
}
UPDATE 2
Manually calling
[self dismissViewControllerAnimated:YES completion:^{
[self viewWillAppear:YES];
}];
Fixes it, but i'd still like some input to why this is necessary ?
Somewhere in the view hierarchy I had missed a call to [super viewWillAppear:].

Table View: setEditing programmatically

NSMutableArray *objects holds some objects which I use to display the content of my table view cells. If objects.count is 0 I would like to enable the editing mode of my table view when viewDidLoad:
- (void)viewDidLoad {
// If there is no content to present enable editing mode
if (self.objects.count == 0) [self setEditing:YES animated:YES];
}
This toggles the self.editButtonItem and inserts a new row (stating "Tap here to add a new element") into my table view:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
if (self.editing) {
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:[self.objects count] inSection:0]]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
else {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:[self.objects count] inSection:0]]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
Unfortunately this setup results in a crash:
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-1914.85/UITableView.m:833
Is it not possible to toggle the editing mode programmatically? If the user touches the self.editButtonItem everything works fine – and as far as I know, this editButton does the same I'm doing in viewDidLoad.
What am I doing wrong?
i think there are 2 different questions here.
one, it is possible to perform setEditing:animated: programmatically.
but i don't think that's what you really want to try to do here. the editing mode is for the user to manually edit the table, and present the little red button on the left, and possibly the little movement indicator on the right if you have those settings set.
the better thing to do is when you find your objects has changed, perform a [self.tableView reloadData];, and just make sure that your UITableViewDataSource protocol methods implemented do the right thing. this will include the implementation of tableView:numberOfRowsInSection: (and possibly also numberOfSections) and also tableView:cellForRowAtIndexPath: . this will cause the items to appear in the tableView as objects changes.

Trigger setEditing: animated: without using an edit button

I have a UITableView with some custom cells in it. In these custom cells I defined a UILongPressGestureRecognizer that triggers the edit mode of this table. So when someone presses and holds a cell for like 1.5 sec, the table goes into edit mode.
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(startEditMode:)];
Which triggers:
- (void)startEditMode:(UISwipeGestureRecognizer *)recognizer {
if (self.allowEdit) {
UITableView *table = (UITableView *)self.superview;
[table setEditing:YES animated:YES];
}
}
But what I want to do is detect when the table goes into edit mode because I need to show/hide some additional buttons in this case. But for some reason in my viewcontroller this is never executed:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
NSLog(#"SET EDITING");
[super setEditing:editing animated:animated];
}
Any suggestion why? Is this just being called when using a proper Edit Button as provided by default in the UINavigationController?
Or how can I detect when my UITableView goes into Edit Mode?
You're sending the message (setEditing) to the table view, you should be sending it to the view controller (presumably a UITableViewController subclass?). It will then take care of the table view for you.
Ok so in case someone else walks into this thread with the same problem, I will show you how I solved this.
In my custom UITableViewCell I have this method now:
- (void)startEditMode:(UISwipeGestureRecognizer *)recognizer {
if (self.allowEdit) {
UITableView *table = (UITableView *)self.superview;
UITableViewController *control = (UITableViewController *)table.dataSource;
[control setEditing:YES animated:YES];
}
}