mercredi 24 juin 2015

Multiple Selection Delete with NSPredicate error in numberOfRowsInSection:

I'm having difficulties updating the numberOfRowsInSection: method after I update an array from the documents folder. I know its something simple, but I think I've just been staring at it for too long to find the solution. I've tried beginUpdates and endUpdates.

Basically, the only time it crashes is when I filter the plist with an NSPredicate. Otherwise, if the category 'show all' is selected I can delete all the rows with no crash.

-(void)viewDidLoad {

    NSArray *array = [[NSArray arrayWithArray:[self returnArrayFromPlist]] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
    self.alertSubArray = [[NSMutableArray alloc] init];
    self.alertSubArray = [NSMutableArray arrayWithArray:array];

    catName = @"ALL"; //Set on load, which loads all items in plist without filtering

    //Creating a horizontal menu to filter the array based on the button they select
        UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
        myButton.frame = CGRectMake(5,self.scrollView.frame.size.height / 2 -10,100,20);     [myButton setTitle:@"ALL" forState:UIControlStateNormal];
        [myButton.titleLabel setTextAlignment:NSTextAlignmentCenter];
        [myButton setTitleColor:[UIColor colorWithRed:(66/255.0) green:(106/255.0) blue:(140/255.0) alpha:1] forState:UIControlStateNormal];
        [myButton setTitleColor:[UIColor colorWithRed:(48/255.0) green:(144/255.0) blue:(251/255.0) alpha:1] forState:UIControlStateSelected];
        [myButton addTarget:self action:@selector(cmdCategroy:) forControlEvents:UIControlEventTouchUpInside];
        [self.scrollView addSubview:myButton];
        myButton.tag = self.categoryArray.count + 1; //setting tag


    for (int y = 0; y < self.categoryArray.count; y++) {
        UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
        myButton.frame = CGRectMake(100 + 5 + 100 * y,self.scrollView.frame.size.height / 2 -10,100,20);
        [myButton setTitle:[self.categoryArray objectAtIndex:y] forState:UIControlStateNormal];
        [myButton.titleLabel setTextAlignment:NSTextAlignmentCenter];
        [myButton setTitleColor:[UIColor colorWithRed:(66/255.0) green:(106/255.0) blue:(140/255.0) alpha:1] forState:UIControlStateNormal];
        [myButton setTitleColor:[UIColor colorWithRed:(48/255.0) green:(144/255.0) blue:(251/255.0) alpha:1] forState:UIControlStateSelected];
        [myButton addTarget:self action:@selector(cmdCategroy:) forControlEvents:UIControlEventTouchUpInside];
        [self.scrollView addSubview:myButton];
        myButton.tag = y; //setting tag for all buttons not 'ALL'
}

//Handle selection of respective button

-(void)cmdCategroy:(id)sender {

   NSInteger tid = ((UIControl *) sender).tag;

   if (tid != self.categoryArray.count + 1) {
    catName = [self.categoryArray objectAtIndex:tid];
    [self filterContentForCategory:catName];
   } else {
    //Selected category is 'ALL' <- different then loading with 'ALL' this is when a user deliberately tap on 'ALL'
    catName = @"ALL";
    NSArray *array = [[NSArray arrayWithArray:[self returnArrayFromPlist]] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
    self.alertSubArray = [NSMutableArray arrayWithArray:array];

    if (self.alertSubArray.count >= 1) {
        [self.editButton setEnabled:YES];
        [self.editButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
    } else {
        [self.editButton setEnabled:NO];
        [self.editButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
    }
}
 [self.tableView reloadData];
}

If Button is NOT 'ALL', then filter :

-(void)filterContentForCategory:(NSString*)category {

NSPredicate *resultPredicate;
if ([category isEqualToString:@"A"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH[c] %@", @"blah"];
    [self filterResultsWithPredicate:resultPredicate];
} else if ([category isEqualToString:@"B"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH[c] %@", @"blah2 "];
    [self filterResultsWithPredicate:resultPredicate];
} else if ([category isEqualToString:@"C"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH[c] %@", @"blah3"];
    [self filterResultsWithPredicate:resultPredicate];
} else if ([category isEqualToString:@"D"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH[c] %@", @"blah4"];
    [self filterResultsWithPredicate:resultPredicate];
} else if ([category isEqualToString:@"E"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH[c] %@", @"blah5"];
    [self filterResultsWithPredicate:resultPredicate];
} else if ([category isEqualToString:@"F"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH[c] %@", @"blah6"];
    [self filterResultsWithPredicate:resultPredicate];
} else if ([category isEqualToString:@"G"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"SELF BEGINSWITH[c] %@", @"blah7"];
    [self filterResultsWithPredicate:resultPredicate];
} else if ([category isEqualToString:@"H"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"(SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@)", @"blah", @"blah",@"blah", @"blah", @"blah", @"blah",@"blah",@"blah",@"blah"];
    [self filterResultsWithPredicate:resultPredicate];
} else if ([category isEqualToString:@"I"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"(SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@)", @"blah9", @"blah9"];
    [self filterResultsWithPredicate:resultPredicate];
} else if ([category isEqualToString:@"J"]) {
    resultPredicate = [NSPredicate predicateWithFormat:@"(SELF BEGINSWITH[c] %@) OR (SELF BEGINSWITH[c] %@)", @"blah", @"blah"];
    [self filterResultsWithPredicate:resultPredicate];
}

}

- (void)filterResultsWithPredicate:(NSPredicate *)predicate {
//Get original array from documents folder so we don't refilter a filtered array
NSArray *filteredResults = [[[self returnArrayFromPlist] filteredArrayUsingPredicate:predicate] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

self.alertSubArray = [NSMutableArray arrayWithArray:filteredResults];

if (filteredResults.count >= 1) {
    [self.editButton setEnabled:YES];
    [self.editButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
} else {
    [self.editButton setEnabled:NO];
    [self.editButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
}
}

UITableView delegate methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.alertSubArray.count;
}

Deleting actual selected rows

- (IBAction)deleteButton:(id)sender {
    if ([self.deleteButton.titleLabel.text isEqualToString:@"Done"]) {
      //Dismiss view
} else {
    // Delete all the selected rows
    NSArray *selectedRows = [self.tableView indexPathsForSelectedRows];

    BOOL deleteSpecificRows = selectedRows.count > 0;
    if (deleteSpecificRows)
    {
        NSMutableArray *stringsOfObjects = [NSMutableArray new];
        for (NSIndexPath *selectionIndex in selectedRows) {
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:selectionIndex];
            [stringsOfObjects addObject:cell.textLabel.text];
        }
             NSLog(@"stringsOfObjects (selected objects) array %@", stringsOfObjects);


        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *path = [paths objectAtIndex:0];

        NSString *plistPath = [path stringByAppendingPathComponent:@"AlertSubscriptions.plist"];

        NSMutableArray *array = [[[NSMutableArray alloc] initWithContentsOfFile:plistPath] mutableCopy];

        [array removeObjectsInArray:stringsOfObjects];
        //removing objects from original array of plist
        [array writeToFile:plistPath atomically:YES];
        //Create a new array from the array minus selected/removed objects
        self.alertSubArray = [NSMutableArray new];
        self.alertSubArray = [NSMutableArray arrayWithArray:array];
        NSLog(@"new array is %@", self.alertSubArray); // returns exactly as wanted

        // Tell the tableView that we deleted the objects
        [self.tableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic]; //works but crashes here with incorrect numberOfRows number

    }
    else
    {

    }

    // Exit editing mode after the deletion.
    [self.tableView setEditing:NO animated:YES];
    [self updateButtonsToMatchTableState]; //Make buttons enabled again

}

}

Again, this all works exactly as wanted until a different menu item is selected. So it's clearly something to do with the filtering. Any help is appreciated

See more ..

Aucun commentaire:

Enregistrer un commentaire