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];
}
}
Related
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];}
I'm seeing a weird effect when inserting/deleting a UITableViewCell in a UITableView with animation (UITableViewRowAnimationTop).
The animation glitch happens when the cell to insert is much bigger than the cell above.
This video shows the glitch in the simulator, yellow cell appears suddenly out of no where when it's supposed to slide from top.
Here is the Xcode project from the video.
Bellow is the cell insertion/animation code.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2 + self.thirdCellVisible;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
if (indexPath.row == 1)
{
if (self.thirdCellVisible)
{
self.thirdCellVisible = !self.thirdCellVisible;
[tableView deleteRowsAtIndexPaths:#[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
}
else
{
self.thirdCellVisible = !self.thirdCellVisible;
[tableView insertRowsAtIndexPaths:#[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
}
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == self.thirdCellIndexPath.row)
{
return 100.0f;
}
return 44.0f;
}
You will have to call
[tableView beginUpdates]
and
[tableView endUpdates]
before and after calling insert/delete methods as below :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2 + self.thirdCellVisible;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
if (indexPath.row == 1)
{
if (self.thirdCellVisible)
{
self.thirdCellVisible = !self.thirdCellVisible;
[self.tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:#[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
}
else
{
self.thirdCellVisible = !self.thirdCellVisible;
[self.tableView beginUpdates];
[tableView insertRowsAtIndexPaths:#[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
}
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == self.thirdCellIndexPath.row)
{
return 100.0f;
}
return 44.0f;
}
According to Apple here:
To animate a batch insertion, deletion, and reloading of rows and
sections, call the corresponding methods within an animation block
defined by successive calls to beginUpdates and endUpdates. If you
don’t call the insertion, deletion, and reloading methods within this
block, row and section indexes may be invalid. Calls to beginUpdates
and endUpdates can be nested; all indexes are treated as if there were
only the outer update block.
At the conclusion of a block—that is, after endUpdates returns—the
table view queries its data source and delegate as usual for row and
section data. Thus the collection objects backing the table view
should be updated to reflect the new or removed rows or sections.
You will have to call [tableView beginUpdates] and [tableView endUpdates] before and after calling insert/delete methods respectively.
An example is provided by Apple on the above link.
Note: If your array and table view items are out of sync, without the begin/end calls an exception will be thrown.
Suggestion: Try first withRowAnimation:UITableViewRowAnimationAutomatic
Here is the link of video of my working code: https://dl.dropboxusercontent.com/u/30316681/480.mov
Below is my working code:
#interface ViewController ()
#property (nonatomic, readwrite) BOOL thirdCellVisible;
#property (nonatomic, strong) NSIndexPath *thirdCellIndexPath;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.thirdCellIndexPath = [NSIndexPath indexPathForRow:2 inSection:0];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2 + self.thirdCellVisible;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == self.thirdCellIndexPath.row)
{
return 100.0f;
}
return 44.0f;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
if (indexPath.row == 1)
{
if (self.thirdCellVisible)
{
self.thirdCellVisible = !self.thirdCellVisible;
[tableView deleteRowsAtIndexPaths:#[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
}
else
{
self.thirdCellVisible = !self.thirdCellVisible;
[tableView insertRowsAtIndexPaths:#[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
}
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = #"id";
UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:cellId];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
NSString *cellTitle = [NSString stringWithFormat:#"Cell %ld", (long)indexPath.row];
cell.textLabel.text = cellTitle;
if(indexPath.row == 2)
cell.backgroundColor = [UIColor yellowColor];
else
cell.backgroundColor = [UIColor clearColor];
return cell;
}
#end
Use [tableView beginUpdates] and [tableView endUpdates] as follow
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
if (indexPath.row == 1)
{
if (self.thirdCellVisible)
{
self.thirdCellVisible = !self.thirdCellVisible;
[self.tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:#[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
}
else
{
self.thirdCellVisible = !self.thirdCellVisible;
[self.tableView beginUpdates];
[tableView insertRowsAtIndexPaths:#[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
}
}
}
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.
In my UIViewController, I have a table view whose cells show text. The datasource and delegate of the UITableView is my UIViewController. The text to be showed by the cells is stored in an NSMutableArray.
I am able to populate the cells with the text initially, but I also want to implement a functionality, when a user clicks on a specific row the cell gets removed and the table is reloaded.
Here's my code and it's details:
taskList is a NSMutableArray
png images are ones that i need to add in every cell
my table contains only one section
the last row of the table will always show "Create New Task" with a "+" sign as an image
as user adds other task (handled by a separate controller), the taask gets added to the current table.The task will have a "-" sign image.
When user clicks on such a row, it will get deleted from the table
UIViewController's code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
taskList = [[NSMutableArray alloc] init];
addNewTask = [[AddTaskViewController alloc] init];
[taskList addObject:#"Create New Task"];
[taskList addObject:#"aaaaa"];
[taskList addObject:#"bbbbb"];
[taskList addObject:#"ccccc"];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
indexNumberInTaskList = [taskList count] - 1;
return [taskList count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:#"myCell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"myCell"];
}
if(indexNumberInTaskList >= 0)
{
cell.textLabel.text = [taskList objectAtIndex:indexNumberInTaskList];
if(indexPath.row == ([taskList count] - 1))
{
cell.imageView.image = [UIImage imageNamed:#"add.png"];
}
else
{
cell.imageView.image = [UIImage imageNamed:#"remove.png"];
}
indexNumberInTaskList = indexNumberInTaskList - 1;
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int selectedRow = indexPath.row;
if(selectedRow == ([taskList count]-1))
{
[self presentViewController:addNewTask animated:YES completion:NULL];
}
else
{
[taskList removeObjectAtIndex:indexPath.row];
[self.createDaily reloadData];
}
}
The least amount of code way would be:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.modelArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
These are only required to batch multiple changes together:
[tableView beginUpdates];
[tableView endUpdates];
You can use didSelectRowAtindexPath method of tableview
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[arrayData removeObjectAtIndex:indexPath.row];
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow: indexPath.row inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
[tableView endUpdates];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[YourArr removeObjectAtIndex:indexPath.row];
[YourTbl reloadData];
}
Under your -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath delegate method,
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath`
NSArray *toBeDeleted = [[NSArray alloc] initWithObjects: indexPath];
// Data deletion
[tableData removeObjectAtIndex:(indexPath.row)];
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:toBeDeleted withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
Edit: seems everybody has the same answer!
Add this method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[arrData removeObjectAtIndex:indexPath.row];
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow: indexPath.row inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
[tableView endUpdates];
}
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.