I'm using Xcode 5.1.1.
Created single view app for an iPhone. I'm testing in Xcode iOS simulator and everything works fine until I try to delete. Checked the code several times. In app "Edit" -> red "Minus" appears on every row then i'm pressing "Minus" and appears red "delete" button, that cant be pressed.
#import "ViewController.h"
#import "AddViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize data;
- (void)viewDidLoad
{
[super viewDidLoad];
data = [[NSMutableArray alloc] initWithObjects: #"item1", #"item2", #"item3", nil];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
-(NSInteger) numberOfSectionsInTableView: (UITableView *) tableView {
return 1;
}
-(NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection:(NSInteger)section {
return [data count];
}
-(UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
[[cell textLabel] setText:[data objectAtIndex:[indexPath row]]];
return cell;
}
// Called after 'Save' is tapped on the AddViewController
- (IBAction) unwindToTableViewController: (UIStoryboardSegue *) sender {
AddViewController *addViewController = (AddViewController *) [sender sourceViewController];
NSString *text = [[addViewController textField] text];
if(![text length] == 0 && ![[text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) {
// add it to the tap of the data source
[data insertObject:text atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
// insert it into tableView
[[self tableView] beginUpdates];
[[self tableView] insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[[self tableView] endUpdates];
}
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[[self tableView] setEditing:editing animated:animated];
}
- (void)tableView:(UITableView *)tableView comitEditingStyle: (UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[data removeObjectAtIndex:[indexPath row]];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
#end
You mispelled commit as comit in the method name. Not sure if this is the problem, but it is certainly a problem. It should be
- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[data removeObjectAtIndex:[indexPath row]];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
You handle deletion, but you don't seem to enable it:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
Sounds like you aren't Reloading Data after the deletion event.
On tap of the delete button, once you remove the data from the data source, call
[self.tableView reloadData];
and see if that works.
This has to do with how you set your autoresizing mask - it's a weird behavior that presented itself on iOS 7. Try calling this in your viewDidLoad function - [self view].autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight and this for your tableView - [tableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth]. I had the same issue with an app and this fixed it.
- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[data removeObjectAtIndex:[indexPath row]];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView reloadData];}
Related
#import "MasterTableViewController.h"
#interface MasterTableViewController ()
#end
#implementation MasterTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self isEditing] ? self.wishListItems.count + 1 : self.wishListItems.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
WishListItem *item = self.wishListItems[indexPath.row];
if (indexPath.row >= [self.wishListItems count] && self.tableView.isEditing) {
cell.textLabel.text = #"New subject";
cell.imageView.image = nil;
} else {
cell.textLabel.text = item.name;
cell.imageView.image = item.photo;
}
return cell;
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
if (editing) {
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:self.wishListItems.count inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
} else {
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:self.wishListItems.count inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
}
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.wishListItems removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView reloadData];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
WishListItem *newItem = [[WishListItem alloc] initWithName:#"New subject" photo:nil price:0.0 andNotes:#"Empty"];
[self.wishListItems insertObject:newItem atIndex:indexPath.row];
[tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView reloadData];
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row >= [self.wishListItems count]) {
return UITableViewCellEditingStyleInsert;
} else {
return UITableViewCellEditingStyleDelete;
}
}
//- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// [self.tableView deselectRowAtIndexPath:indexPath animated:true];
// if (indexPath.row >= self.wishListItems.count && self.editing) {
// [self tableView:tableView commitEditingStyle:UITableViewCellEditingStyleInsert forRowAtIndexPath:indexPath];
// }
//}
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
WishListItem *item = self.wishListItems[indexPath.row];
DetailViewController *detailViewController = (DetailViewController *)segue.destinationViewController;
detailViewController.item = item;
}
}
#end
I changed "number of row in section" and inserted new row but issue
" index 3 beyond bounds [0 .. 2] ", and I changed "number of row in section"
without increment, appear issue " reason: 'attempt to insert row 3 into section 0, but there are only 3 rows in section 0 after the update' "
I double-check a thousand times and still can not find the problem, help who was able to find what is the problem in the code.
In cellForRowAtIndexPath:, you're accessing your array before you do your bounds check, so it will crash when your table is editing.
Only do the array access after the bounds check:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (indexPath.row >= [self.wishListItems count] && self.tableView.isEditing) {
cell.textLabel.text = #"New subject";
cell.imageView.image = nil;
} else {
WishListItem *item = self.wishListItems[indexPath.row];
cell.textLabel.text = item.name;
cell.imageView.image = item.photo;
}
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.effectsTableView beginUpdates];
Effect *effectToBeDeleted =self.effectsArray[indexPath.row];
[self deleteEffectWithName:effectToBeDeleted.name];
[self.effectsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
[self.effectsArray removeObjectAtIndex:indexPath.row];
[self.effectsTableView endUpdates];
}
}
The above function should in theory delete the rows as they are slided and the delete button is pressed. However the row does not delete instead is visible even after the
[self.effectsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
is called. And after the user scrolls to the bottom of the UITableView, while loading the last row, the app obviously crashes with "*** -[__NSArrayM objectAtIndex:]: index 9 beyond bounds [0 .. 8]" error since one of the objects has been deleted from the array.
the cellForRowAtIndexPath is as follows:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.effectsArray)
{
[self loadEffectsInArray];
}
static NSString *cellIdentifier = #"EffectsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
Effect *effectCellEffect = [self.effectsArray objectAtIndex:indexPath.row];
NSString *effectCellText = effectCellEffect.name;
[cell.textLabel setText:effectCellText];
cell.textLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
return cell;
}
Below is the entire .m file for better context:
#import "EffectsManagementTableViewController.h"
#import "Effect+Manage.h"
#import "VLOGAppDelegate.h"
#import "AddEffectViewController.h"
#import "EffectFilterProperty+Manage.h"
#import "Effect.h"
#interface EffectsManagementTableViewController ()
#property (strong, nonatomic) IBOutlet UITableView *effectsTableView;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#property (nonatomic, strong) NSMutableArray *effectsArray;
#property (nonatomic, strong) NSString *currSelectedRowTitle;
#end
#implementation EffectsManagementTableViewController
-(NSString *)currSelectedRowTitle
{
if(!_currSelectedRowTitle)
{
_currSelectedRowTitle = #"";
}
return _currSelectedRowTitle;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
VLOGAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
self.managedObjectContext = appDelegate.managedObjectContext;
self.effectsTableView.dataSource = self;
self.effectsTableView.delegate = self;
}
-(void)viewWillAppear:(BOOL)animated
{
[self loadEffectsInArray];
[self.effectsTableView reloadData];
[self.effectsTableView setNeedsDisplay];
[self.effectsTableView setNeedsLayout];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (!self.effectsArray)
{
[self loadEffectsInArray];
}
return [self.effectsArray count];
}
//4
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.effectsArray)
{
[self loadEffectsInArray];
}
static NSString *cellIdentifier = #"EffectsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
//6
Effect *effectCellEffect = [self.effectsArray objectAtIndex:indexPath.row];
NSString *effectCellText = effectCellEffect.name;
//7
[cell.textLabel setText:effectCellText];
//[cell.detailTextLabel setText:#"5 stars!"];
cell.textLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
//cell.backgroundColor = [UIColor blackColor];
//cell.textLabel.textColor = [UIColor whiteColor];
//cell.detailTextLabel.textColor = [UIColor grayColor];
//cell.textLabel.highlightedTextColor = self.effectsTableView.tintColor;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return YES if you want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.effectsTableView beginUpdates];
Effect *effectToBeDeleted =self.effectsArray[indexPath.row];
[self deleteEffectWithName:effectToBeDeleted.name];
[self.effectsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
[self.effectsArray removeObjectAtIndex:indexPath.row];
//[self loadEffectsInArray];
[self.effectsTableView endUpdates];
//[self.effectsTableView reloadData];
//[self.effectsTableView setNeedsLayout];
//[self.effectsTableView setNeedsDisplay];
}
}
-(void)deleteEffectWithName:(NSString *)effectName
{
NSArray *efpForEffectToBeDeleted = [EffectFilterProperty getEffectFilterPropertiesForEffectName:effectName forImmediateEngagement:NO forManagedObjectContext:self.managedObjectContext];
Effect *effectToBeDeleted = [Effect getEffectWithName:effectName forManagedObjectContext:self.managedObjectContext];
for (int i = 0; i < efpForEffectToBeDeleted.count; i++)
{
EffectFilterProperty *currEFP = efpForEffectToBeDeleted[i];
currEFP.relatedEffect = nil;
currEFP.relatedFilterProperty = nil;
[self.managedObjectContext deleteObject:currEFP];
}
[self.managedObjectContext deleteObject:effectToBeDeleted];
NSError *err = nil;
[self.managedObjectContext save:&err];
if (err != nil) {
//Problem while saving
}
}
-(void)loadEffectsInArray
{
self.effectsArray = [[Effect getAllEffectsForManagedObjectContext:_managedObjectContext] mutableCopy];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Effect *effectCellEffect = [self.effectsArray objectAtIndex:indexPath.row];
self.currSelectedRowTitle = effectCellEffect.name;
[self performSegueWithIdentifier:#"PushedByTableView" sender:self];
}
/*
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:<##"reuseIdentifier"#> forIndexPath:indexPath];
// Configure the cell...
return cell;
}
*/
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"PushedByTableView"])
{
AddEffectViewController *destinationViewController = segue.destinationViewController;
NSString *selectedRowText = self.currSelectedRowTitle;
destinationViewController.effectToManage = [Effect getEffectWithName:selectedRowText forManagedObjectContext:self.managedObjectContext];
}
}
#end
What am I doing wrong here?
where are you beginning your updates, please add
[self.effectsTableView beginUpdates];
before deleting your row and no need of reloading the table when you are writing the begin updates and end updates.
Please don't remove the object from array before deleting the row.
IT'S WORKING
At end of your commitEditingStyle method add this line this will help you
[TableViewForFirstView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
try this code to add beginUpdatesmethod before delete called
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.effectsTableView beginUpdates];
Effect *effectToBeDeleted =self.effectsArray[indexPath.row];
[self deleteEffectWithName:effectToBeDeleted.name];
[self.effectsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
[self.effectsArray removeObjectAtIndex:indexPath.row];
[self loadEffectsInArray];
[self.effectsTableView endUpdates];
}
Try this code:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
Effect *effectToBeDeleted =[self.effectsArray objectAtIndex:indexPath.row];
[self deleteEffectWithName:effectToBeDeleted.name];
[self.effectsArray removeObjectAtIndex:indexPath.row];
[self loadEffectsInArray];
[self.effectsTableView reloadData];
}
As this message, it's crash for reason out of bound, so try check the array index before assign:
Effect *effectToBeDeleted = self.effectsArray > indexPath.row ? self.effectsArray[indexPath.row] : nil;
And
if(self.effectsArray.count > indexpath.row)
[self.effectsArray removeObjectAtIndex:indexPath.row];
else
NSlog("out of bound");
I'm just practicing with UITableView.
Here is what I did so far.
made cells with xib.file from scratch.
Data is stored in P-list.
Using [ MutableCopy] and convert array into mutableArray
It looks little strange but I made the delegate connection using storyboard ,so there's no "self.tableView.delegate = self" line here.
Now the problem is I can delete the objects in the mutableArray but not on UI. The row I selected is remained on the table.
I know "- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath" delegation method works but something goes wrong.
Any Advice is appreciated! Thanks:)
![#import "ViewController.h"
#import "Model.h"
#import "SimpleTableCell.h"
#interface ViewController ()
{
NSMutableArray *_recipesMC;
NSMutableArray *_imagesMC;
Model *_model;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
\[super viewDidLoad\];
// Do any additional setup after loading the view, typically from a nib.
Model *model = \[\[Model alloc\] init\];
\[model getBack\];
NSArray *recipes = model.recipes;
NSArray *images = model.imagesArray;
_recipesMC = \[recipes mutableCopy\];
_imagesMC = \[images mutableCopy\];
}
- (void)didReceiveMemoryWarning
{
\[super didReceiveMemoryWarning\];
// Dispose of any resources that can be recreated.
}
# pragma mark delegat patern
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return \[_recipesMC count\];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)\[tableView dequeueReusableCellWithIdentifier:cellIdentifier\];
if(cell == nil)
{
NSArray *nib = \[\[NSBundle mainBundle\] loadNibNamed:#"Empty" owner:self options:nil\];
cell = \[nib objectAtIndex:0\];
}
cell.nameLabel.text = \[_recipesMC objectAtIndex:indexPath.row\];
if (indexPath.row < \[_recipesMC count\] - 1)
{
UIImage *image = \[UIImage imageNamed:_imagesMC\[indexPath.row\]\];
cell.thumbnailImageView.image = image;
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 78;
}
# pragma mark delegate touch
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%li",(long)indexPath.row);
UIAlertView *alert = \[\[UIAlertView alloc\] initWithTitle:#"HEY" message:\[NSString stringWithFormat:#"%#",_recipesMC\[indexPath.row\]\] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil\];
\[alert show\];
UITableViewCell *cell = \[tableView cellForRowAtIndexPath:indexPath\];
if (cell.accessoryType !=
UITableViewCellAccessoryNone) {
cell.accessoryType =
UITableViewCellAccessoryNone;
}
else
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
\[self performSegueWithIdentifier:#"CellSelectionSegue" sender:self\];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Clicked DELETE BUTTON at %i",indexPath.row);
\[_recipesMC removeObjectAtIndex:indexPath.row\];
\[_imagesMC removeObjectAtIndex:indexPath.row\];
\[self.tableView reloadData\];
NSLog(#"count = %i",\[_recipesMC count\]);
}
# pragma mark Segue
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"Segue");
}
#end
I'm pretty sure your self.tableView is nil.
It's because even if you set self as datasource and delegate, your table will work, but here you seems to have create your UITableView *tableView but didn't link it through your interface (if you do it with the builder).
Or you can simply call tableView rather than self.tableView because the delegate protocole gives you the table.
Just do it and it will work. And then, you can try the solution of Szu.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Clicked DELETE BUTTON at %i",indexPath.row);
[_recipesMC removeObjectAtIndex:indexPath.row];
[_imagesMC removeObjectAtIndex:indexPath.row];
[tableView reloadData];
NSLog(#"count = %i",[_recipesMC count]);
}
Yo should call deleteRowsAtIndexPath:wothRowAnimation:
e.g. in my code:
if (editingStyle == UITableViewCellEditingStyleDelete) {
ElKeyValuePair *pair = [self.locationFavoritesKeyArr objectAtIndex:[indexPath row]];
[self.locationFavoritesKeyArr removeObjectAtIndex:[indexPath row]];
ELCarpark *carpark = [self.agglomeration carparkForUid:[pair.val1 intValue]];
[carpark removeFromFavoritesAgglomerationUid:self.agglomeration.uid];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
Adding this code to the method tableView:commitEditingStyle:forRowAtIndexPath should remove the row from the data source and the UI.
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[_recipesMC removeObjectAtIndex:indexPath.row];
[_imagesMC removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:indexPath withRowAnimation:YES];
}
Finally remove the reloadData instruction.
I had my app working fine on iOS 6. With the upgrade I stopped being able to delete rows from my UITableView.
I've a button in my prototype cell.
Here is the button's function:
- (IBAction)deleteCell:(id)sender {
UIButton *btn = (UIButton*) sender;
UITableViewCell *cell = (UITableViewCell*) btn.superview.superview;
NSIndexPath *indexPath = [_tableView indexPathForCell:cell];
if([names count] > 9) {
int index = indexPath.row;
[names removeObjectAtIndex:index];
[photos removeObjectAtIndex:index];
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
}
}
The problem is my index variable is always 0.
I tried another solution:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
int index = indexPath.row;
[names removeObjectAtIndex:index];
[photos removeObjectAtIndex:index];
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
}
}
This solution doesn't work either. Nothing happens when I swipe right.
Try this sample tutorial,
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>
{
NSMutableArray *arryData1;
NSMutableArray *arryData2;
IBOutlet UITableView *tableList;
}
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(void)viewDidLoad
{
[super viewDidLoad];
arryData1 = [[NSMutableArray alloc] initWithObjects:#"MCA",#"MBA",#"BTech",#"MTech",nil];
arryData2 = [[NSMutableArray alloc] initWithObjects:#"Objective C",#"C++",#"C#",#".net",nil];
tableList.editing=YES;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arryData1 count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier= #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] ;
}
cell.textLabel.text = [arryData1 objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [arryData2 objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
int index = indexPath.row;
[arryData1 removeObjectAtIndex:index];
[arryData2 removeObjectAtIndex:index];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableList.editing)
{
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
I quess the problem is you're not reloading data again thus it's staying in cache memory
You can try to reload data with [tableView reloadData]; this method to the below of
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
this code line in your second solution.
To show delete button on cell swipe you must implement this delegate method.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return YES if you want the specified item to be editable.
return YES;
}
Try this, i hope this will work for you.
Use the tableview commiteditingstyle method to delete a cell/row of the tableviewcontroller.
Here is the workable code snip:
-(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[ArrayHoldsCellObj removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
Note that the ArrayHoldsCellObj is the Array object you must declare and assign each cell to the area index.
You can set the button tag = cell.index in cellForRowAtIndexPath.
And then
UITableViewCell *cell = (UITableViewCell *)
[tableView cellForRowAtIndexPath:
[NSIndexPath indexPathForRow:btn.tag inSection:0]];
so you can get the index
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//add code here for when you hit delete
[dataSourceArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
Suppose there is Custom Cell A & B of different Height.
Custom Cell A is loaded Default on UITableView. When User will Select Cell A it will remove that Cell and Add Cell B to that Position and vise versa. It will do the animation of re-sizing in Accordion style.
To do this, you should have a property (or key if using a dictionary) in your data array to keep track of what cell you want at each indexPath, and use an if-else statement in cellFroRowAtIndexPath to dequeue the correct cell. In didSelectRowAtIndexPath, you would check that property, set it to the opposite one, and then reload the table. You would also need to implement heightForRowAtIndexPath, and check that same property to determine which height to return.
After Edit:
If you just need to keep track of one selected cell, then create a property (I call it selectedPath) to hold that value and check it in heightForRowAtIndexPath and cellForRowAtIndexPath. I created two cells in the storyboard, one a simple UITableViewCell and the other a custom cell of class RDCell. I'm not sure if this gives the animation you want, but give it a try and see if it's close:
#import "TableController.h"
#import "RDCell.h"
#interface TableController ()
#property (strong,nonatomic) NSArray *theData;
#property (nonatomic) NSIndexPath *selectedPath;
#end
#implementation TableController
- (void)viewDidLoad {
[super viewDidLoad];
self.theData = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight"];
self.selectedPath = [NSIndexPath indexPathForRow:-1 inSection:0];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.selectedPath isEqual:indexPath]) {
return 90;
}else{
return 44;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.selectedPath isEqual:indexPath]) {
RDCell *cell = [tableView dequeueReusableCellWithIdentifier:#"RDCell" forIndexPath:indexPath];
cell.label.text = self.theData[indexPath.row];
return cell;
}else{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.theData[indexPath.row];
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSIndexPath *oldPath = self.selectedPath;
self.selectedPath = indexPath;
[self.tableView reloadRowsAtIndexPaths:#[indexPath,oldPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
**Got this amazing Solution, its working great...**
#implementation NetworkCentreTable
{
NSMutableArray *arr;
BOOL chk;
int onSelectCount;
NSIndexPath *onSelectTrack;
}
- (void)viewDidLoad
{
[super viewDidLoad];
arr=[[NSMutableArray alloc] initWithObjects:#"1",#"1",#"1",#"1",#"1",#"1",#"1",#"1",#"1",nil];
onSelectCount=0;
static NSString *CellIdentifier1 = #"NetworkCell2";
UINib *nib = [UINib nibWithNibName:#"NetworkCentreCellBig" bundle:nil];
[self.tblNetworkCentre registerNib:nib forCellReuseIdentifier:CellIdentifier1];
}
#pragma mark -
#pragma mark Custom Network TableView delegate and Datasource
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [arr count];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier1 = #"NetworkCentreCell";
static NSString *CellIdentifier2 = #"NetworkCentreCellBig";
if(self.selectedRowIndex && indexPath.row == self.selectedRowIndex.integerValue)
{
NetworkCentreCell *cell = (NetworkCentreCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
UIViewController *controller=[[UIViewController alloc] initWithNibName:CellIdentifier2 bundle:nil];
cell=(NetworkCentreCell *)controller.view;
return cell;
}
else
{
NetworkCentreCell *cell = (NetworkCentreCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
UIViewController *controller=[[UIViewController alloc] initWithNibName:CellIdentifier1 bundle:nil];
cell=(NetworkCentreCell *)controller.view;
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
onSelectCount++;
NSLog(#"num=%d",onSelectCount);
self.selectedIndexPath = indexPath;
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation: UITableViewRowAnimationNone];
self.selectedRowIndex = [NSNumber numberWithInteger:indexPath.row];
[self.tblNetworkCentre deselectRowAtIndexPath:indexPath animated:YES];
//First we check if a cell is already expanded.
//If it is we want to minimize make sure it is reloaded to minimize it back
if( onSelectCount==1 )
{
[tableView beginUpdates];
NSIndexPath *previousPath = [NSIndexPath indexPathForRow:self.selectedRowIndex.integerValue inSection:0];
self.selectedRowIndex = [NSNumber numberWithInteger:indexPath.row];
onSelectTrack=indexPath;
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:previousPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
if(onSelectTrack.row!=indexPath.row)
{
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:onSelectTrack] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
onSelectTrack=indexPath;
onSelectCount=0;
[self tableView:tableView didSelectRowAtIndexPath:onSelectTrack];
}
if(self.selectedRowIndex.integerValue == indexPath.row && onSelectCount==2)
{
[tableView beginUpdates];
self.selectedRowIndex = [NSNumber numberWithInteger:-1];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
onSelectCount=0;
[tableView endUpdates];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(self.selectedRowIndex && indexPath.row == self.selectedRowIndex.integerValue)
{
return 280;
}else{
return 85;
}
}
You can call [yourTableview reloadData] in didSelectRowAtIndexPath method.
Then in numberOfRowsInSection give a new count. In heightForRowAtIndexpath specify the custom heights.
In cellForRowAtIndexpath add custom cells.