0

I have custom contact book sorted by A-Z sections. I am trying to add to an array selected contacts

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

NSMutableDictionary *contactInfo = [NSMutableDictionary new];

Cell *cell = (Cell *)[self.contTableView cellForRowAtIndexPath:indexPath];

//NSLog(@"CELL %@", cell.contact.fullname);

if (!cell.contact.contactChecked) {

    cell.contactImage.image = [UIImage imageNamed:@"cell_blue_circle.png"];
    cell.contact.contactChecked = YES;
    //NSLog(@"DID SELECT %@", cell.contact.fullname);
    NSLog(@"index checked row %d section %d", indexPath.row, indexPath.section);
    [contactInfo setValue:cell.contact.fullname forKey:@"name"];
    [contactInfo setValue:cell.contact.numbers.firstObject forKey:@"phone"];

    [self.seletedPeople insertObject:contactInfo atIndex:indexPath.row];

} else {
     NSLog(@"index unchecked row %d section %d", indexPath.row, indexPath.section);
    cell.contactImage.image = [UIImage imageNamed:@"cell_gray_circle.png"];
    cell.contact.contactChecked = NO;
    [self.seletedPeople removeObjectAtIndex:indexPath.row];
}

NSLog(@"DICT SELECTED %@", self.seletedPeople);

}

What happens, that in some cell app crashing with error

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM insertObject:atIndex:]: index 1 beyond bounds for empty array' *** First throw call stack: (0x29c02fef 0x38150c8b 0x29b1cf8f 0xf7fe9 0x2d36e56b 0x2d41d43b 0x2d2d2a91 0x2d24d38f 0x29bc8fed 0x29bc66ab 0x29bc6ab3 0x29b13201 0x29b13013 0x313f2201 0x2d2b7a59 0x10c075 0x386dcaaf) libc++abi.dylib: terminating with uncaught exception of type NSException

UPDATE:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *cellID = @"Cell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];

if (searchResults) {

    //NSLog(@"CELL %@", cell.contact.fullname);
    contact = [searchResults objectAtIndex:indexPath.row];
    cell.contact = contact;
    cell.firstNameLabel.text = contact.fullname;
    cell.avatar.image = contact.image;
    cell.avatar.layer.borderColor = [UIColor grayColor].CGColor;
    cell.avatar.layer.borderWidth = 0.5;
    cell.avatar.layer.cornerRadius = 25.0;
    cell.avatar.layer.masksToBounds = YES;
    cell.number.text = contact.numbers.firstObject;

} else {

    NSString *sectionTitle = [[[namesDictionary allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]
                              objectAtIndex:indexPath.section];
    NSArray *sectionContacts = [namesDictionary objectForKey:sectionTitle];
    contact = [self getContactFromArray:[sectionContacts objectAtIndex:indexPath.row]];

    cell.firstNameLabel.text = [sectionContacts objectAtIndex:indexPath.row];

    cell.avatar.image = contact.image;
    cell.avatar.layer.borderColor = [UIColor grayColor].CGColor;
    cell.avatar.layer.borderWidth = 0.5;
    cell.avatar.layer.cornerRadius = 25.0;
    cell.avatar.layer.masksToBounds = YES;
    cell.number.text = contact.numbers.firstObject;

    cell.contact = contact;

    cell.tag = indexPath.row;
}

if (contact.contactChecked) {
    cell.contactImage.image = [UIImage imageNamed:@"cell_blue_circle.png"];
} else {
    cell.contactImage.image = [UIImage imageNamed:@"cell_gray_circle.png"];

}


return cell;

}

1
  • Please post code to display cellForRowAtIndexPath: better to see how you are displaying your cell Commented Apr 9, 2015 at 18:32

5 Answers 5

2

The way I use in such cases. I create a model class and load the tableview with models. Now when i select a cell or deselect a cell. I just add that model in another array. After that when i de select the already selected cell, i can get the same model from the indexpath.row and then i can use NSArray method to fetch that model in that selected array and remove it from there. To fix your issue you can use indexPath.row as another key in dictionary during selection. After that when you deselect the cell use a predicate to get the added dictionary from the array that you are using to store selected ones. Once you find it delete it from the array.

Sign up to request clarification or add additional context in comments.

1 Comment

I have updated your answer with a check. Do update your code other wise it will crash.
1

the problem here is the coupling of model with view objects , you shouldn't inquire about a certain property from the view itself (in your case the Cell) however the contact checked should have a reflect on its model from the data source object (the one you used to feed the cellForRowAtIndexPath: , where it should be inquired from.

Otherwise the code is buggy and unstable due to that coupling since it might point to an empty object

Comments

0

The problem is here:

[self.seletedPeople insertObject:contactInfo atIndex:indexPath.row];

if selectedPeople is empty and the user clicks on row 2, then it's going to try to insert contactInfo into row 2 which is "beyond the bounds of an empty array". Simply use addObject: instead. You'll also need to change how you remove items from that array then (probably better to use a dictionary instead).

1 Comment

My issue with removing objects. these 2 objects is dictionary and count as 1 object
0

The solution was adding contact record id to my dictionary and search with predicate this contact id. then remove it. kudos to @jassi

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {



    NSMutableDictionary *contactInfo = [NSMutableDictionary new];

    Cell *cell = (Cell *)[tableView cellForRowAtIndexPath:indexPath];

    if (!cell.contact.contactChecked) {

        cell.contactImage.image = [UIImage imageNamed:@"cell_blue_circle.png"];
        cell.contact.contactChecked = YES;
        //NSLog(@"DID SELECT %@", cell.contact.fullname);
        NSLog(@"index checked %@ ", [indexPath description]);
        [contactInfo setValue:cell.contact.fullname forKey:@"name"];
        [contactInfo setValue:cell.contact.numbers.firstObject forKey:@"phone"];
        [contactInfo setValue:@(cell.contact.contactId) forKey:@"contactId"];


        [self.seletedPeople addObject:contactInfo];

    } else {
         NSLog(@"index unchecked %@", [indexPath description]);
        cell.contactImage.image = [UIImage imageNamed:@"cell_gray_circle.png"];
        cell.contact.contactChecked = NO;
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"contactId == %d", cell.contact.contactId];
        NSArray *resultTemp = [self.seletedPeople filteredArrayUsingPredicate:predicate];

    if(resultTemp.count>0)
        [self.seletedPeople removeObject:resultTemp[0]];


    }

    NSLog(@"DICT SELECTED %@", self.seletedPeople);
}

Comments

-1

As user2320861 said, the problem is on the line where you use insertObject. I would do the following:

  1. Change self.selectedPeople to a NSMutableDictionary using the following code:

    //in your @interface
    @property (nonatomic, strong) NSMutableDictionary *selectedPeople;
    
  2. Change the code in didSelectCellAtIndexPath to:

    //Since phone numbers are unique.
    self.selectedPeople[cell.contact.numbers.firstObject] = contactInfo;
    
  3. Retrieve all of the contacts later using this code:

    for(id key in self.selectedPeople) {
        NSDictionary contactInfo = [self.selectedPeople objectForKey:key];
        //Do something with that contactInfo
    }
    

1 Comment

Didn't understand your answer. I don't need to retrieve it. I need deselect and remove from an array the object I have tapped twice. In some indexes it's working well and on some indexes it's crashing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.