Xcode commitEditingStyle UITableViewCellEditingStyleDelete is not working - ios

I have a project I have been working on. The code giving me problems worked yesterday and I haven't made any changes to that part of the code since, when I tried to run it today it wasn't working.
The problem is that when I swipe across the cell to delete it it's not detected and commitEditingStyle method is never run.
I also made another project just to test out the commitEditingStyle method and it was working fine. I also cleaned the project(Product -> Clean) and reset the iOS simulator.
What else can I try?
Here's my code, don't worry about NSUserDefaults, that's for saving the changes after you delete the cell.
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES; }
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.taskObjects removeObjectAtIndex:indexPath.row];
NSMutableArray *newTaskObjectsData = [[NSMutableArray alloc] init];
for(Model *task in self.taskObjects)
{
[newTaskObjectsData addObject:[self taskObjectAsPropertyList:task]];
}
[[NSUserDefaults standardUserDefaults] setObject:newTaskObjectsData forKey:USER_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}

I Hope it's help you
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.taskObjects removeObjectAtIndex:indexPath.row];
NSMutableArray *newTaskObjectsData = [[NSMutableArray alloc] init];
for(Model *task in self.taskObjects)
{
[newTaskObjectsData addObject:[self taskObjectAsPropertyList:task]];
}
[[NSUserDefaults standardUserDefaults] setObject:newTaskObjectsData forKey:USER_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; // please set automatic animation
}
// here you can reload your tableview
[self.tasksTableView reloadData];

I found out what was wrong! I had another method in the viewController that I was not aware was there.
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}
Fixed it by setting the return value to UITableViewCellEditingStyleDelete.

Related

Deleted row in tableview is reappearing when navigating back

Have friendsviewcontroller in which have uibarbuttonItem to edit friends list and other uibarbuttonitem to create groups for group chatrooms.
Have multiple segue for switching view controllers.
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Groups";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"New" style:UIBarButtonItemStylePlain target:self
action:#selector(actionNew)];
self.tableView.separatorInset = UIEdgeInsetsZero;
chatrooms = [[NSMutableArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([PFUser currentUser] != nil)
{
[self refreshTable];
}
else LoginUser(self);
}
#pragma mark - User actions
- (void)actionNew
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Create New Group" message:nil delegate:self
cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex: (NSInteger)buttonIndex=
{
if (buttonIndex != alertView.cancelButtonIndex)
{
UITextField *textField = [alertView textFieldAtIndex:0];
if ([textField.text isEqualToString:#""] == NO)
{
PFObject *object = [PFObject objectWithClassName:PF_CHATROOMS_CLASS_NAME];
object[PF_CHATROOMS_NAME] = textField.text;
[object saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
if (error == nil)
{
[self refreshTable];
}
else [ProgressHUD showError:#"Network error."];
}];
}
}
}
- (void)refreshTable
{
[ProgressHUD show:nil];
PFQuery *query = [PFQuery queryWithClassName:PF_CHATROOMS_CLASS_NAME];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (error == nil)
{
[chatrooms removeAllObjects];
for (PFObject *object in objects)
{
[chatrooms addObject:object];
}
[ProgressHUD dismiss];
[self.tableView reloadData];
}
else [ProgressHUD showError:#"Network error."];
}];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [chatrooms count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
PFObject *chatroom = chatrooms[indexPath.row];
cell.textLabel.text = chatroom[PF_CHATROOMS_NAME];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *chatroom = [chatrooms objectAtIndex:indexPath.row];
[chatrooms removeObjectAtIndex:chatroom];
//[chatrooms removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
PFObject *chatroom = chatrooms[indexPath.row];
NSString *roomId = chatroom.objectId;
CreateMessageItem([PFUser currentUser], roomId, chatroom[PF_CHATROOMS_NAME]);
ChatView *chatView = [[ChatView alloc] initWith:roomId];
chatView.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:chatView animated:YES];
}
Deleted row in table view reappears when navigate back to the TableView
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *chatroom = [chatrooms objectAtIndex:indexPath.row];
[chatrooms removeObjectAtIndex:chatroom];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
Im unable to locate what piece of code i m missing or what exactly i m doing wrong.
If anyone can please point out to that.
Will appreciate so much.
Thanks.
When committing deletion, your code removes objects from chatrooms which is data source of the table view in your case, but this happens in your app's memory, the source from which chatrooms is populated does not change. Thus, speaking in MVC, the app's model state is not updated after the view's state is changed.
Every time the table view is showed up, your code populates chatrooms in refreshTable, if the model's state hasn't been changed, the code gets same list as before, thus the table view doesn't change.
EDIT: Instead of using another approach to refresh the table view, you need to think about what does your app do in this table view. If user can delete stuff in the table view, should your app update model (This model can be a local or remote database, a property list file, etc.) too? If yes, then update model when user inserts or deletes rows in the table view; well, if not, then you are asking a question that is not a problem, or maybe the table view should turn off editing.
EDIT1:
If you do need to update data, based on your code, you may need to do something like this:
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *chatroom = [chatrooms objectAtIndex:indexPath.row];
[chatrooms removeObjectAtIndex:indexPath.row];
PFQuery *query = [PFQuery queryWithClassName:PF_CHATROOMS_CLASS_NAME];
[query deleteChatroom:chatroom];
[tableView deleteRowsAtIndexPaths:#[indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
That is, you may need to implement method deleteChatroom: of class PFQuery.

Delete row in UITableView in conjunction with Parse

I am trying to delete a row in a UITableView (PFQueryTableViewController). The object deletes in the class, but is only reflected in the table when I refresh the table. Here is the code I am using.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *object = [self.objects objectAtIndex:indexPath.row];
[object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
[tableView reloadData];
}];
}
}
Sussed it.
Instead of [tableView reloadData], I've used [self loadObjects].
However, the usual delete animation is not there.
You have to make all UI updates in main thread.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *object = [self.objects objectAtIndex:indexPath.row];
[object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[tableView deleteRowsAtIndexPaths:#[indexPath]withRowAnimation:UITableViewRowAnimationFade];
}];
}
}

UITableView crashes when pressing delete button in edit mode

When editing the UITableView, the app usually crashes with this error after someone presses the "delete" button on the uitableviewcell. This usually happens for the first item in the table view, but has happened to others. I'm sorry for being so vague, I can provide any additional infomation. I'm just very confused on why this happens and why it happens when it does.
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
}
-(void)viewWillAppear:(BOOL)animated{
[_matchIDS removeAllObjects];
_matchIDS = [[NSMutableArray alloc]init];
_matchIDS = [[NSUserDefaults standardUserDefaults] valueForKey:#"allMatchIDS"];
[self.tableView reloadData];
}
-(void)viewWillDisappear:(BOOL)animated{
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:_matchIDS forKey:#"allMatchIDS"];
[defaults synchronize];
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _matchIDS.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = _matchIDS[indexPath.row];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_matchIDS removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
The error results from trying to remove an element from the _matchIDS array, which is immutable.
[_matchIDS removeObjectAtIndex:indexPath.row];
You attempt to make the array mutable here:
-(void)viewWillAppear:(BOOL)animated{
[_matchIDS removeAllObjects];
_matchIDS = [[NSMutableArray alloc]init];
_matchIDS = [[NSUserDefaults standardUserDefaults] valueForKey:#"allMatchIDS"]; // <---
[self.tableView reloadData];
}
but the line marked above replaces _matchIDS, discarding the NSMutableArray you instantiated. You probably want to use the mutableCopy method instead, resulting in something like:
_matchIDS = [[[NSUserDefaults standardUserDefaults] valueForKey:#"allMatchIDS"] mutableCopy];

How to save tableView cell's checkmark after reload view use NSUserDefaults?

I'm new to ios development, and I'm using checkmark for cells in a UITableView.
I want storing checked cell in a NSUserDefaults database, When I reload the app, the checked cell that previously selected will be display, I'm try to defferent ways, but still failed to implement it.
Anybody can help me? I would be highly appreciate it. Sorry, my english is not good.
My code is below:
#import "FirstRowSubview.h"
#interface FirstRowSubview ()
#end
#implementation FirstRowSubview
#synthesize array = _array;
#synthesize lastIndexPath = _lastIndexPath;
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *list = [[NSMutableArray alloc] initWithObjects:#"ffgfgh", #"564654", #"56548", #"fgmjfgmf", #"ggkdj", nil];
self.array = list;
[list release];
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.array = nil;
}
#pragma mark -
#pragma mark - TableView Datasource Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *subviewCells = #"Cells";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:subviewCells];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:subviewCells];
}
NSUInteger oldRow = [_lastIndexPath row];
cell.accessoryType = (indexPath.row == oldRow && _lastIndexPath != nil) ?
UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
cell.textLabel.text = [_array objectAtIndex:indexPath.row];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[NSNumber numberWithInt:_lastIndexPath.row] forKey:#"lastIndexPath"];
[defaults synchronize];
return cell;
}
#pragma mark -
#pragma mark - TableView Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int newRow = [indexPath row];
int oldRow = (_lastIndexPath != nil) ? [_lastIndexPath row] : -1;
if (newRow != oldRow) {
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:_lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
[indexPath retain];
[_lastIndexPath release];
_lastIndexPath = indexPath;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
It can be easy to store and retrieve checked cell(s) information with NSUserDefaults.
NSUserDefaults can store the data interms of Key / Value pair. Here in your case value could be boolean and key could combination of NSString & indexpath.row from UITableView.
You can make a functions like,
- (NSString *)getKeyForIndex:(int)index
{
return [NSString stringWithFormat:#"KEY%d",index];
}
- (BOOL) getCheckedForIndex:(int)index
{
if([[[NSUserDefaults standardUserDefaults] valueForKey:[self getKeyForIndex:index]] boolValue]==YES)
{
return YES;
}
else
{
return NO;
}
}
- (void) checkedCellAtIndex:(int)index
{
BOOL boolChecked = [self getCheckedForIndex:index];
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:!boolChecked] forKey:[self getKeyForIndex:index]];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Here, you can check for previously checked cells like
static NSString *subviewCells = #"Cells";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:subviewCells];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:subviewCells];
}
cell.textLabel.text = [_array objectAtIndex:indexPath.row];
if([self getCheckedForIndex:indexPath.row]==YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
//Use checkedCellAtIndex for check or uncheck cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self checkedCellAtIndex:indexPath.row];
if([self getCheckedForIndex:indexPath.row]==YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
P.S. Please, note that, this method will only useful and suggested if order of data from your NSArray will always in same order. Other then NSUserDefaults you've options like SQLite Database or plist file or any other option! Thanks :)
This is a basic example of how to create an array of NSIndexPaths based on the current selection of the table and then saving that array into NSUserDefaults.
-(void)viewDidLoad
{
[super viewDidLoad];
for (NSIndexPath *indexPath in [[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:#"mySavedMutableArray"]) {
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
Here you can add objects to the array as they are selected
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:#"mySavedMutableArray"] addObject:indexPath];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Here you'll remove the deselected object from the array.
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:#"mySavedMutableArray"] removeObject:indexPath];
[[NSUserDefaults standardUserDefaults] synchronize];
}
The simplest way to get your code working is just put one line in view did load method as follow:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults valueForKey:#"lastIndexPath"])
_lastIndexPath = [defaults valueForKey:#"lastIndexPath"];
This will solve your problem :)
Happy Coding :)

Sqlite database and swipe to delete

The project I'm working on required me to use a sqlite database, and I've been trying to get swipe to delete to work on my tableView:
[self performSelectorOnMainThread:#selector(removeMovieFromCache:) withObject:[NSNumber numberWithInt:movieId] waitUntilDone:YES];
[db performSelectorOnMainThread:#selector(performQuery:) withObject:[NSString stringWithFormat:#"DELETE FROM movie WHERE id = %d", movieId] waitUntilDone:YES];
[db performSelectorOnMainThread:#selector(performQuery:) withObject:[NSString stringWithFormat:#"DELETE FROM new_movies WHERE new_movie_id = %d", movieId] waitUntilDone:YES];
[self removeMovieFromCache:movieId];
[db performQueryWithFormat:#"DELETE FROM movie WHERE id = %d", movieId];
[db performQueryWithFormat:#"DELETE FROM new_movies WHERE new_movie_id = %d", movieId];
[db performQuery:#"COMMIT"];
That's the code to get rid of something from my database. When I try to apply this to my swipe to delete command of:
-
(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)movieID
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
//code goes here
}
}
It just doesn't want to work, what am I doing wrong?
In your tableView Data Source, try implementing this:
(UITableViewCellEditingStyle)tableView:(UITableView*)tableView editingStyleForRowAtIndexPath:(NSIndexPath*)indexPath
{
return UITableViewCellEditingStyleDelete;
}
(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)movieID
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// First delete the row from the table, then delete from the DB, finally reload the date in the table
[theTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
// code to delete from DB
[theTable reloadData];
}
}
(replace "theTable" with whatever you've called your table!)

Resources