So, this issue follows on from a previous issue, but I decided to post a new question to keep things relevant and tidy.
Basically, when the following piece of code is called, there is no difference between UITableViewRowAnimationFade and UITableViewRowAnimationNone:
- (void) setEditing:(BOOL)editing animated:(BOOL)animated
{
[tvController.tableView beginUpdates];
if (editing == YES) {
[tvController.tableView deleteRowsAtIndexPaths:[settingsArray objectAtIndex:0] withRowAnimation:UITableViewRowAnimationFade];
}else {
UITableViewRowAnimation animation = animated ? UITableViewRowAnimationFade : UITableViewRowAnimationNone;
[tvController.tableView reloadRowsAtIndexPaths:[settingsArray objectAtIndex:0] withRowAnimation:animation];
[tvController.tableView reloadSectionIndexTitles];
self.navigationItem.hidesBackButton = editing;
}
[tvController.tableView endUpdates];
}
Greatly appreciate any help. It still enters editing mode, but does not animate into it, depsite YES being passed into animated.
EDIT: The animation works fine when I'm actually deleting things using the following code:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *stuff = [documentsPath stringByAppendingPathComponent:#"stuff.plist"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:stuff];
if (fileExists) {
NSMutableDictionary *propertyList = [[NSMutableDictionary alloc] initWithContentsOfFile:enteredPlaces];
[propertyList removeObjectForKey:[[settingsArray objectAtIndex:1] objectAtIndex:indexPath.row]];
[propertyList writeToFile:stuff atomically:YES];
}
[[settingsArray objectAtIndex:1] removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}
}
It just doesn't work when the user presses the edit button and the table goes into editing mode, the tableview just snaps statically into edit mode.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[db DeleteData:[NSString stringWithFormat:#"%d",indexPath.row]];
[data removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation: UITableViewRowAnimationFade];
}
}
I have same scenario in my application, I was facing the similar issue. I guess below function will solve your issue :
- (void) setEditing:(BOOL)editing animated:(BOOL)animated
{
[tvController.tableView setEditing:editing animated:animated]; //this LOC is added
[tvController.tableView beginUpdates];
if (editing == YES) {
[tvController.tableView deleteRowsAtIndexPaths:[settingsArray objectAtIndex:0] withRowAnimation:UITableViewRowAnimationFade];
} else {
UITableViewRowAnimation animation = animated ? UITableViewRowAnimationFade : UITableViewRowAnimationNone;
[tvController.tableView reloadRowsAtIndexPaths:[settingsArray objectAtIndex:0] withRowAnimation:animation];
[tvController.tableView reloadSectionIndexTitles];
self.navigationItem.hidesBackButton = editing;
}
[tvController.tableView endUpdates];
}
-(void)deleteRecord:(NSInteger)recordNo:(NSInteger)sectionNo:(BOOL)isEditMode:(BOOL)isAnimate {
if(isEditMode){
NSIndexPath *indexP=[NSIndexPath indexPathForRow:recordNo inSection:sectionNo];
[tvController.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexP, nil] withRowAnimation:UITableViewRowAnimationLeft];
}
else {
if(isAnimate)
[tvController.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexP, nil] withRowAnimation:UITableViewRowAnimationFade];
else
[tvController.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexP, nil] withRowAnimation:UITableViewRowAnimationNone];
[tvController.tableView reloadSectionIndexTitles];
self.navigationItem.hidesBackButton = editing;
}
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(reload) userInfo:nil repeats:NO];
}
-(void)reload {
[table reloadData];
}
if the only thing that you are annoyed by is the fact that the delete doesn't fade, it is because you are anticipating something that the interface doesn't provide.
you mentioned that you know individual cells can be set to be non-editable, and this is the standard way to do this. the mechanism simply does not anticipate not using the UITableViewDataSource to provide the information about what to display (or, in your case, what is in the data being changed) simply by hitting the edit/done button.
by trying to combine the two, you are confusing the animation that is supposed to happen.
probably the best you can do is something like the following (and the animation duration and length could possibly be 0, since you're asking for separate animation in the tableView), which will cause your animation to occur after the animation that opens up editing mode.
- (void) setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated]; // possibly not necessary depending upon your class hierarchy
[tvController.tableView setEditing:editing animated:animated];
[UIView animateWithDuration:0.25 delay:0.05 options:UIViewAnimationCurveLinear
animations:^{
[tvController.tableView beginUpdates];
if (editing == YES) {
[tvController.tableView deleteRowsAtIndexPaths:[settingsArray objectAtIndex:0] withRowAnimation:UITableViewRowAnimationFade];
} else {
UITableViewRowAnimation animation = animated ? UITableViewRowAnimationFade : UITableViewRowAnimationNone;
[tvController.tableView reloadRowsAtIndexPaths:[settingsArray objectAtIndex:0] withRowAnimation:animation];
[tvController.tableView reloadSectionIndexTitles];
self.navigationItem.hidesBackButton = editing;
}
[tvController.tableView endUpdates];
}
completion:nil];
}
Related
I have a UITableView which lies in a NavigationController that is in a popover. So, I put an edit/done UIToolBarItem which works fine and you can see the delete accessory icon showing up. However, when I rearrange the items, the edit/done button stops working...
I debugged and it still gets called but it doesn't seem to update and is sort of preventing any further updates from other buttons. Is this possibly a problem with the simulator?
Thanks for the help in advance!
Edit: Adding code
addButton = [[UIBarButtonItem alloc] initWithTitle:#"Edit" style:UIBarButtonItemStyleBordered target:self action:#selector(editTable:)];
And later on the method:
- (IBAction) editTable: (id) sender
{
if ([[addButton title] isEqualToString:EDIT_STRING]) {
[addButton setTitle:DONE_STRING]; //enabling edit mode
[super setEditing:YES animated:YES];
[[self tableView] setEditing:YES animated:YES];
}
else {
[addButton setTitle:EDIT_STRING]; //done with editing
[[self tableView] setEditing:NO animated:YES];
[super setEditing:NO animated:YES];
[[self tableView] setNeedsDisplay];
[[self tableView] reloadData];
}
}
The second part is definitely called as the addButton text is changing. However, it stops working once I make an edit (such as re-arranging a row)
Alright,
I seemed to have called [tableView beginUpdates] and never called endUpdates, which was causing all updates to not be registered. If anyone else does that...
- (void)tableView:(UITableView *)tableview commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tv reloadData];
}
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tv setEditing:editing animated:YES];
}
my data is show on the table whn i select data to delet its delted from database but not from table , i go back to other view and again come to the delete table view then delete data is not show again
i am using this code ...
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPath withRowAnimation:(UITableViewRowAnimation)animation
{
NSLog(#"Hello");
}
-(void) tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
// int row = [indexPath row];
[self.table beginUpdates];
if (editingStyle == UITableViewCellEditingStyleDelete)
{
Hadits *delHadit = [self.allBookMarks objectAtIndex:indexPath.row];
dbAccess *dbmethods = [[dbAccess alloc] init];
NSInteger delHaditid = delHadit.haditid;
[dbmethods deleteBookMark:delHaditid];
[dbmethods release];
}
[self deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[self.table endUpdates];
NSLog(#"Hello");
[self.table reloadData];
}
...Help needed..
Regards Haseeb
in view will appear prepare your array which having record and in commitEditing add one line.
[self viewWillApear:YES];
and in viewWillAppear add this line
[yourTable reloadData];
after fetching data from db.
There is little mistake (or I think the relevant code is not shown). You have deleted the entry from the database, but I think you have missed to delete the same from your array which acts as your tableview datasource.
-(void) tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.table beginUpdates];
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// [self.table deleteRowsAtIndexPaths:[NSArray arrayWithObject: indexPath] withRowAnimation:UITableViewRowAnimationFade];
Hadits *delHadit = [self.allBookMarks objectAtIndex:indexPath.row];
dbAccess *dbmethods = [[dbAccess alloc] init];
NSInteger delHaditid = delHadit.haditid;
[dbmethods deleteBookMark:delHaditid];
[dbmethods release];
[self.allBookMarks removeObject:delHadit];/// change of code
}
//[self.table reloadData];
[table endUpdates];
}
I have a UITableViewController that is presented with a list of choices. After the user taps one, I'd like to return to the previous view. The return seems too quick with the code I'm using though. I'd like to pause for 0.2 seconds or so to give the user time to see their selection become checked. Here's the code I'm using now:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger oldSelection = [[selectedCriteria objectAtIndex:criteriaSection] integerValue];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Since there's a "none" selection, we don't deselect if the user taps the one that's already selected
if ([indexPath row] != oldSelection + 1) {
NSIndexPath *selectionIndexPath = [NSIndexPath indexPathForRow:oldSelection+1 // Shift down for "None"
inSection:[indexPath section]];
UITableViewCell *checkedCell = [tableView cellForRowAtIndexPath:selectionIndexPath];
[checkedCell setAccessoryType:UITableViewCellAccessoryNone];
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
[selectedCriteria replaceObjectAtIndex:criteriaSection
withObject:[NSNumber numberWithUnsignedInteger:[indexPath row]-1]];
}
[[self navigationController] popViewControllerAnimated:YES];
}
Is there a good way to add a short delay before the view controller is popped?
Hope this help.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger oldSelection = [[selectedCriteria objectAtIndex:criteriaSection] integerValue];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Since there's a "none" selection, we don't deselect if the user taps the one that's already selected
if ([indexPath row] != oldSelection + 1) {
NSIndexPath *selectionIndexPath = [NSIndexPath indexPathForRow:oldSelection+1 // Shift down for "None"
inSection:[indexPath section]];
UITableViewCell *checkedCell = [tableView cellForRowAtIndexPath:selectionIndexPath];
[checkedCell setAccessoryType:UITableViewCellAccessoryNone];
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
[selectedCriteria replaceObjectAtIndex:criteriaSection
withObject:[NSNumber numberWithUnsignedInteger:[indexPath row]-1]];
}
[self performSelector:#selector(dismissController) withObject:nil afterDelay:0.2];
}
This give you a 0.2 seconds delay to call the function "dismissController".
The function "dismissController".
- (void) dismissController {
[[self navigationController] popViewControllerAnimated:YES];
}
Have you tried -performSelector:withObject:afterDelay ?
sleep(0.2) worked for me
I have a UITableView, where I extend/shrink the cells with the following code.
I save the last 2 indexPaths to perform a reloadRowsAtIndexPaths: on it.
Now I added a UISearchBar to the header for section 0. If I tab the searchBar, a KeyBoard is displayed on top of the UITableView — so far so good.
But I want the user to be able to touch the Cells and disable the KeyBoard. To do so, I test if the searchbox is the first responder inside the -tableView:didSelectRowAtIndexPath:
But doing so will lead to a "SIGKILL" in one of the rows marks 1, 2, 3
I really don't understand why
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Article *article = [articles objectAtIndex:indexPath.row];
ArticleCell *cell = (ArticleCell*)[self.tableView dequeueReusableCellWithIdentifier:#"articelcell"];
if (cell == nil)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"ExtendibleCell" owner:self options:nil] objectAtIndex:0];
}
//....
cell.articleName.text = [NSString stringWithFormat:#"%#",article.name ];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([searchBar isFirstResponder]) {
[searchBar resignFirstResponder];
}
[orderTableDelegate receiveSelectedArticleName:[[articles objectAtIndex:indexPath.row] name]];
firstSelected = lastSelected;
lastSelected = indexPath;
if (lastSelected == firstSelected && firstSelected != nil) {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:lastSelected] withRowAnimation:CELL_ANIMATION]; //1
lastSelected = nil;
firstSelected = nil;
return;
}
if (lastSelected != nil) {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:CELL_ANIMATION];//2
}
if (firstSelected != nil) {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:firstSelected] withRowAnimation:CELL_ANIMATION];//3
}
}
-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section ==0) {
if (searchBar == nil) {
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
[searchBar setShowsBookmarkButton:YES];
[searchBar setKeyboardType:UIKeyboardTypeAlphabet];
[searchBar setBarStyle:UIBarStyleBlack];
[searchBar setShowsCancelButton:YES];
[searchBar setDelegate:self];
}
return searchBar;
}
return nil;
}
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([indexPath isEqual:lastSelected] && lastSelected!=firstSelected) {
return [[(Article *)[articles objectAtIndex:indexPath.row] sizesAndPrices] count]*PACKAGESIZE_PRICE_BUTTON_HEIGHT +30;
}
return 40.0;
}
edit
I cleaned up my code for -tableView:didSelectRowAtIndexPath:, but the problem stays the same
#property(nonatomic,retain) NSIndexPath *firstSelected;
#property(nonatomic,retain) NSIndexPath *lastSelected;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[orderTableDelegate receiveSelectedArticleName:[[articles objectAtIndex:indexPath.row] name]];
self.firstSelected = nil;
self.firstSelected = self.lastSelected;
self.lastSelected = nil;
self.lastSelected = [indexPath retain];
if (self.firstSelected == self.lastSelected) {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:self.firstSelected] withRowAnimation:CELL_ANIMATION];
[self.firstSelected release];
[self.lastSelected release];
self.firstSelected = nil ;
self.lastSelected = nil ;
} else {
if (self.firstSelected != nil) {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:self.firstSelected] withRowAnimation:CELL_ANIMATION];
}
if (self.lastSelected != nil) {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:self.lastSelected] withRowAnimation:CELL_ANIMATION];
}
}
if ([searchBar isFirstResponder]) {
[searchBar resignFirstResponder];
}
}
firstSelected = lastSelected;
lastSelected = indexPath;
This leads me to believe that lastSelected is an instance variable? If this is the case, you are not properly retaining it, and there is no guarantee that it is still alive beyond the scope of this method. The indexPath passed in the didSelectRowAtIndexPath: argument needs to be retained if you are going to use it after it's execution.
Keep in mind, if you do that, you need better memory management throughout that method...i.e. releasing lastSelected before changing it's value or setting it to nil.
Assuming firstSelected and lastSelected are instance variables, you could do something like this. (all the releasing and != checking would go away if you made them retained properties and used the setter)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([searchBar isFirstResponder]) {
[searchBar resignFirstResponder];
}
[orderTableDelegate receiveSelectedArticleName:[[articles objectAtIndex:indexPath.row] name]];
if (firstSelected != lastSelected) {
[firstSelected release];
firstSelected = [lastSelected retain];
}
if (lastSelected != lastSelected) {
[lastSelected release];
lastSelected = [indexPath retain];
}
if (lastSelected == firstSelected && firstSelected != nil) {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:lastSelected] withRowAnimation:CELL_ANIMATION]; //1
[lastSelected release];
lastSelected = nil;
[firstSelected release];
firstSelected = nil;
return;
}
if (lastSelected != nil) {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:CELL_ANIMATION];//2
}
if (firstSelected != nil) {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:firstSelected] withRowAnimation:CELL_ANIMATION];//3
}
}
I just add this methods in .h file :
- (IBAction)EditTable:(id)sender;
- (IBAction)DeleteButtonAction:(id)sender;
and in .m file :
(IBAction)DeleteButtonAction:(id)sender{
[tableList removeLastObject];
[Table reloadData];
}
(IBAction) EditTable:(id)sender{
if(self.editing)
{
[super setEditing:NO animated:NO];
[Table setEditing:NO animated:NO];
[Table reloadData];
[self.navigationItem.leftBarButtonItem setTitle:#"Edit"];
[self.navigationItem.leftBarButtonItem setStyle:UIBarButtonItemStylePlain];
}
else
{
[super setEditing:YES animated:YES];
[Table setEditing:YES animated:YES];
[Table reloadData];
[self.navigationItem.leftBarButtonItem setTitle:#"Done"];
[self.navigationItem.leftBarButtonItem setStyle:UIBarButtonItemStyleDone];
}
}
when I run the program and click the delete button (red button) the program is stop !
whats the problem ? please any help ?
you are evil :(
OK, again my code in .h file is :
- (IBAction)EditTable:(id)sender;
- (IBAction)DeleteButtonAction:(id)sender;
and in .m file is :
- (IBAction)DeleteButtonAction:(id)sender{
[tableList removeLastObject];
[Table reloadData];
}
- (IBAction) EditTable:(id)sender{
if(self.editing)
{
[super setEditing:NO animated:NO];
[Table setEditing:NO animated:NO];
[Table reloadData];
[self.navigationItem.leftBarButtonItem setTitle:#"Edit"];
[self.navigationItem.leftBarButtonItem setStyle:UIBarButtonItemStylePlain];
}
else
{
[super setEditing:YES animated:YES];
[Table setEditing:YES animated:YES];
[Table reloadData];
[self.navigationItem.leftBarButtonItem setTitle:#"Done"];
[self.navigationItem.leftBarButtonItem setStyle:UIBarButtonItemStyleDone];
} }
when I run the program and click the delete button (red button) the program is crash ! whats the problem ? please any help ?
If I am not wrong then you want to delete the cell of the tableView when delete button is clicked....
You need to call one other method of tableview:
//To Delete the Data
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
// Updates the appearance of the Edit|Done button as necessary.
[super setEditing:editing animated:animated];
[tblViewBM setEditing:editing animated:YES];
// Disable the add button while editing.
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:
(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//Use your Array from which you need to delete the data.
NSMutableDictionary *dict=(NSMutableDictionary *)[appDel.BookMarkAry objectAtIndex:indexPath.row];
type=[dict valueForKey:#"type"];
[appDel.BookMarkAry removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
I am sure this will Definately help you to delete the cell with data from array also.