UIActionSheet for deleting a UITableView cell on cancel keeps showing pressed Delete button
When deleting a row in a table view, I want to show an action sheet asking for confirmation in certain situations. When the action sheet is answered with "Yes" (the destructive action), I delete the table row and everything is fine. But when Cancel is pressed, I still see the Delete button in a pressed state.
What I do in tableView:commitEditingStyle
when deleting is this:
BlockBasedActionSheet *askSheet =
[[BlockBasedActionSheet alloc]
initWithTitle:@"Delete entry?"
cancelButtonTitle:@"No"
destructiveButtonTitle:@"Yes, delete child also records"
cancelAction:^{
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
if (cell.showingDeleteConfirmation) {
cell.editing = NO;
cell.editingAccessoryView = nil;
cell.editing = YES;
}
}
destructiveAction:deleteBlock];
[askSheet showInView:self.view];
[askSheet release];
What's also strange is that the cell's property showingDeleteConfirmation
is NO
, although the Delete button is still visible.
I am using a self-made block-based action sheet implementation. Maybe there lies the error, although I seem to get the correct cell in the cancel block.
So, how can I reset the Delete button state back to "unpressed" and remove it, and turn the round delete button back to horizontal, like it happens when I tap somewhere on the screen?
Helper class BlockBasedActionSheet.h
:
@interface BlockBasedActionSheet : UIActionSheet<UIActionSheetDelegate> {
}
@property (copy) void (^cancelBlock)();
@property (copy) void (^destructiveBlock)();
- (id)initWithTitle:(NSString *)title cancelBut开发者_如何学CtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle cancelAction:(void (^)())cancelBlock destructiveAction:(void (^)())destructiveBlock;
@end
Implementation file BlockBasedActionSheet.m
:
#import "BlockBasedActionSheet.h"
@implementation BlockBasedActionSheet
@synthesize cancelBlock = _cancelBlock, destructiveBlock = _destructiveBlock;
- (id)initWithTitle:(NSString *)title cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle cancelAction:(void (^)())cancelBlock destructiveAction:(void (^)())destructiveBlock
{
self = [super initWithTitle:title delegate:self cancelButtonTitle:cancelButtonTitle destructiveButtonTitle:destructiveButtonTitle otherButtonTitles: nil];
if (self) {
_cancelBlock = Block_copy(cancelBlock);
_destructiveBlock = Block_copy(destructiveBlock);
}
return self;
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
NSAssert(actionSheet == self, @"Wrong Action Sheet passed");
if (buttonIndex == [self cancelButtonIndex]) {
if (self.cancelBlock) {
self.cancelBlock();
}
} else {
if (self.destructiveBlock) {
self.destructiveBlock();
}
}
}
@end
So, it works by replacing the first code snippet with this
BlockBasedActionSheet *askSheet =
[[BlockBasedActionSheet alloc]
initWithTitle:@"Delete entry?"
cancelButtonTitle:@"No"
destructiveButtonTitle:@"Yes, delete also child records"
cancelAction:^{
// this resets the delete button
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
destructiveAction:deleteBlock];
[askSheet showInView:self.view];
[askSheet release];
Reloading the row does the trick.
From the documentation for tableView:commitEditingStyle
: You should not call setEditing:animated: within an implementation of this method. If for some reason you must, invoke it after a delay by using the performSelector:withObject:afterDelay: method.
My understanding is that this method is called once the delete button is beginning to disappear (hence showingDeleteConfirmation
is NO
) and so the stuff inside your if statement inside your block won't be called. If you set a breakpoint in there, am I right?
In any case, you might want to do as the documentation says and just have the table go back into editing mode after a millisecond delay.
edit/update
Created a new Navigation based project in Xcode. Changed this code. Set the table to show 10 rows with each row displaying its indexpath as the text. http://dl.dropbox.com/u/2180315/crazycell.zip if you want the whole thing. You'll need to swipe to delete, I didn't make a dedicated delete button.
Calling setEditing
on the cell object does nothing, even if performSelector...
is used (I don't know why). But you can call setEditing
on the tableView
which as far as I can tell does what you want it to do (brings it back to the horizontal delete icons, with no delete button).
If this doesn't solve your problem then I'm really not sure what else can be done :/
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
BlockBasedActionSheet *askSheet =
[[BlockBasedActionSheet alloc]
initWithTitle:@"Delete entry?"
cancelButtonTitle:@"No"
destructiveButtonTitle:@"Yes, delete child also records"
cancelAction:^{
[self.tableView setEditing:YES animated:YES];
}
destructiveAction:^{
NSLog(@"Delete block called");
}];
[askSheet showInView:self.view];
[askSheet release];
}
精彩评论