0

I have a mutable array of objects that each have multiple properties that can be shown in a detail view.

I have set up the ability to search by a property and it works fine. It shows the filtered array according to the characters searched, but when I swipe to delete within that filtered array (have not yet canceled out of search bar), it deletes the row from the filtered table and the object from the filtered array according to the index path.

I use that same index path to delete the row from the main table and the corresponding object (all within commitEditingStyle), but as you can probably see the indexPath.row for a certain object on the filtered mutable array will not necessarily correspond with the same object using the same indexPath on the main mutable array. (For example, if the main array is Bob, Jamie, Sarah, Tom, and I search for "To", Tom will show but at index 0 so it would delete Bob in the main array when I try to delete Tom.)

I would like for the user to be able to delete items from search contents and the same item and its properties be deleted from both arrays and tables. Normal deletion straight from the main table view and array works fine. Here is the code:

- (void)tableView:(UITableView *)tableView commitEditingStyle: 
    (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath: 
    (NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {

        if (isFiltered == YES) {
            // Then we are in filtered search results, delete from both arrays and table views

           [self.personArray removeObjectAtIndex:indexPath.row]
           [self.filteredArray removeObjectAtIndex:indexPath.row]
           [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

    }   else {     // normal table view, just remove at master array and table view

           [self.personArray removeObjectAtIndex:indexPath.row]
           [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

    }
  }
}

You can probably see how the indexPath.row wouldn't match up to the same items in each array.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • Get current person with `ObjectClass *person = [self.filteredArray objectAtIndex:indexPath.row]; Find the index of that person in `self.personArray` (name are uniques? Find what's differentiate them, equality in each properties?), and you have the index to delete. – Larme Mar 18 '18 at 19:07
  • [Deleting from UISearchController's filtered search results](https://stackoverflow.com/q/27656678) – jscs Mar 18 '18 at 19:12
  • @Larme thanks, this was a solution. As a new member I'm not sure how to mark the question as answered using your comment. – ben22145 Mar 18 '18 at 20:02
  • You can't mark a comment as the resolution. You can do one of two things: ask @Larme to expand the comment into an answer and then mark that, or go ahead and [post the solution yourself](https://stackoverflow.com/help/self-answer). – jscs Mar 18 '18 at 21:45
  • As Josh said, you can't. I'll post a complete solution tomorrow if needed (it's already late where I leave). – Larme Mar 18 '18 at 21:46

1 Answers1

1

Let's assume for clarity and sake of the example that personArray and filteredArray are populated with objects of class MyPerson.

Suppose we don't filter for starter:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyCustomCell *cell = [tableView dequeue...];
    MyPerson *person = [self.personArray objectAtIndex:indexPath.row];
    cell...configureWithThatPerson
    return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    {
         [self.personArray removeObjectAtIndex:indexPath.row];
         [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }

What you should do in the logic part in fact in pseudo code (deletePerson:on: doesn't exist):

MyPerson *personToDelete = [self.personArray objectAtIndex:indexPath.row];
[self deletePerson:personToDelete on:self.personArray];

Which is of course simplified by (because you already know the index):

[self.personArray removeObjectAtIndex:indexPath.row];

So keep that logic:

MyPerson *personToDelete = [self.filteredArray objectAtIndex:indexPath.row];
[self deletePerson:personToDelete on:self.personArray];
[self deletePerson:personToDelete on:self.filteredArray];

Now there are a different possibilities with implementation of deletePerson:on::
• Find the index (various indices if they are duplicates? Is that your case) of that object in self.personArray Obviously for filteredArray it's the indexPath.row. and remove it.
• Use a NSPredicate to filter it.

In all cases, you might need or not to implement isEqual: depending on the solution, but you have to know what differentiate two MyPerson objects:
Is that equality on all its properties?
You can check on a unique identifier?
Only a match on the name? Etc.

Then you can play maybe with indexOfObject:, indexOfObjectPassingTest:, etc.

Larme
  • 24,190
  • 6
  • 51
  • 81