Consider the following plain and simple UITableViewController: when you tap a row, it logs the selected row, and when you swipe and delete, it removes an item in the model and reloads the data.
#interface DummyTableViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *items;
#end
#implementation DummyTableViewController
- (instancetype)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self)
{
_items = [ #[ #"A", #"B", #"C", #"D", #"E" ] mutableCopy];
}
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
cell.textLabel.text = self.items[indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.items removeObjectAtIndex:indexPath.row];
[tableView reloadData];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Row %# tapped.", self.items[indexPath.row]);
}
In iOS6, this all works as expected, but in iOS7 I get the following behavior: after a row has been removed and the data has been reloaded, the first next tap on a table cell is ignored. It is only the second tap that triggers a table cell select again. Any idea what might be causing this or how to work around it? Issue should be easy to reproduce in iOS7 with the above code.
The tableview is in editing state when you delete a particular row. SO you have to turn off the editing state to allow the tableView to go back to the selection mode. Change your code to this -
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.items removeObjectAtIndex:indexPath.row];
// Turn off editing state here
tableView.editing = NO;
[tableView reloadData];
}
}
Related
I have two viewControllers, ViewController and TableViewController. the ViewController has a button, when pressed the TableViewController will start. the TableViewContoller contains 5 rows.
what I am trying to do is, when I press only the even rows I should go back to ViewController. To solve this problem, we can use unwindSegue, but I do not know how to have the segue respond to the even rows in the table.
please let me know how to make a row in the table linked to the segue
below is the code for TableViewController
code:
#import "TableViewController.h"
#interface TableViewController ()
#property NSArray *tableData;
#end
#implementation TableViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.tableData = [NSArray arrayWithObjects:#"Android",
#"iOS",
#"swift",
#"objective-c",
#"openCV",nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section {
return [self.tableData count];
}
-(UITableViewCell *) tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [self.tableData objectAtIndex:indexPath.row];
cell.imageView.image = [UIImage imageNamed:#"images.jpg"];
return cell;
}
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath {
NSLog(#"%li", indexPath.row);
NSLog(#"%#", [self.tableData objectAtIndex:indexPath.row]);
}
#end
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath {
if(indexPath.row % 2 == 0) {
// Even row...
}
}
I used two(canEditRowAtIndexPath and commitEditingStyle ) methods for delete rows based on index, whenever I went to next view and coming back to the table view deleted rows are again appeared.
How can I delete the rows permanently in table view? it would be very helpful to me.
Seems like you just delete the data from UI, so you got the problem.
You must delete the data from your source and UI at the same time.
Just reference this code:
#interface ViewController ()
#property UITableView* tableView;
#property NSMutableArray* dataArray;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_dataArray = [[NSMutableArray alloc] init];
for (int i = 0; i<10; i++) {
[_dataArray addObject:[NSString stringWithFormat:#"Test%d",i]];
}
_tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds];
_tableView.dataSource = self;
_tableView.delegate = self;
[self.view addSubview:_tableView];
_tableView.editing = true;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _dataArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:#"MyTableCell"];
if (nil == cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyTableCell"];
}
cell.textLabel.text = [_dataArray objectAtIndex:indexPath.row];
return cell;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return true;
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete) {
//Delete data from source
[_dataArray removeObjectAtIndex:indexPath.row];
//Delete row from UI
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}
}
#end
Hope it can help you.
Use NSMutableArray as your UITableView's datasource.
In commitEditingStyle Delegate....
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[datasourceArray removeObjectAtIndex:indexPath.row];
}
}
I am having such an issue right now. I have a UIViewController that has a UITableView, I have it set up so that when the UITableView is in editing mode it returns 3 - circles with the check marks. My UITableView has custom cells with in image and text. When I put the UITableView in edit mode, I am trying to pass an array of the images from multiple selected rows to a second view controller to use those images in a collection view, but I am just having a hard time passing the array of images. Any suggestions would be appreciated.
here is my TableView code:
-(void)didTapEditBUtton:(id)sender{
if ([self.ribbonTableView isEditing]) {
viewButton.hidden = YES;
headerLabel.hidden = NO;
[ribbonTableView setEditing:NO animated:YES];
[selectButton setTitle:#"select"];
}
else {
[selectButton setTitle:#"Cancel"];
// Turn on edit mode
headerLabel.hidden = YES;
viewButton.hidden = NO;
[ribbonTableView setEditing:YES animated:YES];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection (NSInteger)section{
return [ribbonsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
RibbonCustomCell *cell = (RibbonCustomCell *) [ribbonTableView dequeueReusableCellWithIdentifier:#"RibbonDetail"];
if (cell != nil)
{
RibbonsInfo *ribbonsInfo = [ribbonsArray objectAtIndex:indexPath.row];
//NSLog(#"%#", ribbonsInfo);
//Ribbon Image
cell.ribbonImageView.image = ribbonsInfo.ribbonImage;
cell.ribbonLabel.text = ribbonsInfo.ribbonName;
}
return cell;
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return 3;
}
-(void)tableView:(UITableView *)tableView didSelectRowsAtIndexPath:(NSIndexPath *)indexPath{
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
}
You should take the property of NSMutableArray...
#property (nonatomic, strong) NSMutableArray *selectedImages;
- (void)viewDidLoad {
[super viewDidLoad];
self.selectedImages = [NSMutableArray new];
}
now when you select or deselect the cell the delegates are called -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%#",indexPath);
RibbonsInfo *ribbonsInfo = [ribbonsArray objectAtIndex:indexPath.row];
[self.selectedImages addObject:ribbonsInfo.ribbonImage];
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%#",indexPath);
if (self.selectedImages.count > 0) {
[self.selectedImages removeObjectAtIndex:indexPath.row];
}
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return 3;
}
Now the selectedImages array contains the selected cell images and you can pass this array.
Hope it will solve your problem.
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'm fairly new to this and am stuck on a problem. I can't get the ability to edit a table view i've created...
I have a button on the top right corner of the app that says "Edit" and - (IBAction)editTable:(id)sender, I've tried numerous attempts to get to edit this list I've created...
#implementation XYZViewController
#synthesize animalNames;
- (void)viewDidLoad
{
[super viewDidLoad];
//create array called animal names
animalNames = [[NSArray alloc]initWithObjects:
#"Cow",
#"Dog",
#"Cat",
#"Dear",
#"Penguin",
#"Lion",
#"Leapord",
#"Eal",
#"Snake",
#"Moth",
#"Cheetah",
#"Turtle"
, nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.animalNames count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = #"MainCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
cell.textLabel.text = [self.animalNames objectAtIndex:indexPath.row];
return cell;
}
- (IBAction)editTable:(id)sender
{
NSLog(#"Editing");
[super setEditing:TRUE];
[self.tableView setEditing:TRUE];
self.editing = YES;
}
#end
Using Xcode 5.
You need to implement following methods to support table view editing:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
You should declare animalNames as NSMutableArray as you are going edit it. Then you need to override some delegate methods to perform edit in tableview.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
NSString *sourceItem = _animalNames[sourceIndexPath.row];
[_animalNames removeObjectAtIndex:sourceIndexPath.row];
[_animalNames insertObject:sourceItem atIndex:destinationIndexPath.row];
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete){
[_animalNames removeObjectAtIndex:indexPath.row];
[_tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
You can stop editing in editTable method like
- (IBAction)editTable:(id)sender
UIBarButtonItem *button = (UIBarButtonItem *)sender;
if ([button.title isEqualToString:#"Edit"]) {
button.title = #"Done";
[self.tableView setEditing:TRUE];
} else {
button.title = #"Edit";
[self.tableView setEditing:NO];
}
}
Hope this will help you
To edit the table view you need to call
[self.tableView setEditing:YES animated:YES]; on the table which you are using then
You have to implement the delegate method
tableView:commitEditingStyle:forRowAtIndexPath:
method to enable the deleting of rows. In order to delete the rows you need to use
Then Do this..
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
//Remove the object at the index we need to delete
[YourTableArray removeObjectAtIndex:indexPath.row];
//Delete the rows at the Indexpath.
[YourTable deleteRowsAtIndexPaths:[[NSArray alloc]initWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationRight];
[reminder_table reloadData];
//Set the table to editing NO.
[YourTable setEditing:NO animated:YES];
}
Please find below link for your reference
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/ManageInsertDeleteRow/ManageInsertDeleteRow.html#//apple_ref/doc/uid/TP40007451-CH10-SW19