bugphix
bugphix

Reputation: 95

Crash during UITableView moveRowAtIndexPath method

I have an array of strings which i am already showing in my uitableview.

When edit is enabled for my uitableview, I am trying to move a string from say 4th row to 3rd row and i get EXC_BAD_ACCESS in the insert object at index part of my code when i debug this..

[myStringsArray insertObject:name atIndex:toIndexPath.row]; 

However if i do not debug and just build and run, i get to print the following line, and then it crashes without seeing EXC_BAD_ACCESS in my console.

NSLog(@"re-ordered myStringsArray array");

Here is my all code for the moveRowAtIndexPath method:

// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectoryPath = [paths objectAtIndex:0]; 
    NSString *path = [documentsDirectoryPath stringByAppendingPathComponent:@"MyStrings.plist"]; 

    //re-order array
    NSString *name = [myStringsArray objectAtIndex:fromIndexPath.row];
    [myStringsArray removeObjectAtIndex:fromIndexPath.row];
    [myStringsArray insertObject:name atIndex:toIndexPath.row];

    NSLog(@"re-ordered myStringsArray array");
    if([myStringsArray writeToFile:path atomically: YES]){NSLog(@"write succesful");}
    else {NSLog(@"write failed");}

    [myTable reloadData];
}

Any ideas why it thinks that i'm trying to access something that's not there?

Correct me if I am wrong but my mutable array is already allocated and if the remove method worked, why wouldn't the insert method work?

Thank you

Upvotes: 3

Views: 2556

Answers (4)

Abdul Rehman Butt
Abdul Rehman Butt

Reputation: 113

in myStringsArray declaration, write like nsmutable arrary initwithObjects, , nil ], and make sure property in .h file is strong.

Upvotes: 0

Paresh Navadiya
Paresh Navadiya

Reputation: 38239

In TableView Delegate method do following with your myStringArray (as TableView DataSource)

 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath 
 {   
   NSString *name = [[myStringsArray objectAtIndex:sourceIndexPath.row] retain];
   [myStringsArray removeObjectAtIndex:sourceIndexPath.row];
   [myStringsArray insertObject:name atIndex:destinationIndexPath.row];
   [name release];
 }

And Add two new Delegate in your .h file like this

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath 
{    
  return YES;
}

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
   toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath 
{
  return proposedDestinationIndexPath;
}

Upvotes: 0

Ramesh India
Ramesh India

Reputation: 107

I have tried like you but it no doubt make crash , becuase i think delegate execution may not in collaboration with the moving of the rows by user if there is more lines of code in data source method (from my observation). Actually when you move the rows the appearance means only in UITableView cells are adjusted but in back ground it's data is also adjusting , so there are some chances such as when you are moving a row it was already moved but its data resource such as array or dictionary anything is not adjusted according to its move then it will give you EXE bad access kk .

So the code should be very less in the below method to make sure it should not crash.

[myArray exchangeObjectAtIndex:fromIndexPath.row withObjectAtIndex:toIndexPath.row];

Use this code in side this method it will work without crashing.

  • (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath

Upvotes: 0

Vladimir
Vladimir

Reputation: 170839

When you remove object from array it gets released so there's a good chance that its retain count goes to 0 and it gets deallocated. To avoid premature deallocation you can retain and release your object:

NSString *name = [[myStringsArray objectAtIndex:fromIndexPath.row] retain];
[myStringsArray removeObjectAtIndex:fromIndexPath.row];
[myStringsArray insertObject:name atIndex:toIndexPath.row];
[name release];

Or better use built-in NSMutableArray method for swapping objects you found yourself:

[myStringsArray exchangeObjectAtIndex:fromIndexPath.row withObjectAtIndex:toIndexPath.row];

Upvotes: 5

Related Questions