0

For some reason NSPredicate isn't filtering my UITableView (it's supposed to be filtering my TableView by selections made in a UIPickerView). Users make their pickerview selections, press the GO button (segue is attached from Pickerview to Table View controller).

Any idea as to why it isn't working? See code below.

ViewController.m (TABLE VIEW CONTROLLER)

- (int)numberOfSectionsInTableView: (UITableView *)tableview

{

    return 1;

}

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

    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return [searchResults count];




    } else {
        return [Strains count];

    }



}



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


    static NSString *strainTableIdentifier = @"StrainTableCell";

    StrainTableCell *cell = (StrainTableCell *)[tableView dequeueReusableCellWithIdentifier:strainTableIdentifier];
    if (cell == nil) 


        cell = [[StrainTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strainTableIdentifier];



        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"StrainTableCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];

    if (tableView == self.searchDisplayController.searchResultsTableView) {
       NSLog(@"Using the search results");

        cell.titleLabel.text = [[searchResults objectAtIndex:indexPath.row] objectForKey:@"Title"];
        cell.descriptionLabel.text = [[searchResults objectAtIndex:indexPath.row] objectForKey:@"Description"];
        cell.ratingLabel.text = [[searchResults objectAtIndex:indexPath.row] objectForKey:@"Rating"];
        cell.ailmentLabel.text = [[searchResults objectAtIndex:indexPath.row] objectForKey:@"Ailment"];
        cell.actionLabel.text = [[searchResults objectAtIndex:indexPath.row] objectForKey:@"Action"];
        cell.ingestLabel.text = [[searchResults objectAtIndex:indexPath.row] objectForKey:@"Ingestion"];

        NSLog(@"%@", searchResults);


    } else {
        NSLog(@"Using the FULL LIST!!");
        cell.titleLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:@"Title"];
         cell.descriptionLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:@"Description"];
         cell.ratingLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:@"Rating"];
        cell.ailmentLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:@"Ailment"];
        cell.actionLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:@"Action"];
        cell.ingestLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:@"Ingestion"];

    }


return cell;

}




- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    NSPredicate *resultPredicate = [NSPredicate 
                                    predicateWithFormat:@"Title contains[cd] %@",
                                    searchText];

    searchResults = [Strains filteredArrayUsingPredicate:resultPredicate];


}





-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString
                               scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
                                      objectAtIndex:[self.searchDisplayController.searchBar
                                                     selectedScopeButtonIndex]]];

    return YES;
}



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


    StrainDetailViewController *detailViewController = [[StrainDetailViewController alloc] initWithNibName:@"StrainDetailViewController" bundle:nil]; if ([searchResults count]) {

        detailViewController.title = [[searchResults objectAtIndex:indexPath.row] objectForKey:@"Title"];
        detailViewController.strainDetail = [searchResults objectAtIndex:indexPath.row];

    } else {

        detailViewController.title = [[Strains objectAtIndex:indexPath.row] objectForKey:@"Title"];
        detailViewController.strainDetail = [Strains objectAtIndex:indexPath.row];
        NSLog(@"%@", Strains);
    }

    [self.navigationController pushViewController:detailViewController animated:YES];



    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)PickerViewControllerDidFinish:(PickerViewController *)viewController {
  [self.navigationController popViewControllerAnimated:YES];

}

PickerViewController.h

@protocol PickerViewControllerDelegate;

@interface PickerViewController : UIViewController {


    UIPickerView *pickerView;

    NSMutableArray *array1;
    NSMutableArray *array2;
    NSMutableArray *array3;



    NSArray *Strains;
    NSArray *searchResults;

    NSMutableData *data;



}

- (IBAction)buttonpressed:(UIButton *)sender;

@property (nonatomic, weak) id<PickerViewControllerDelegate> delegate;

@property (nonatomic, retain) IBOutlet UIPickerView *pickerView;

- (void)populateArray1;
- (void)populateArray2;
- (void)populateArray3;




@end

@protocol PickerViewControllerDelegate <NSObject>

- (void)PickerViewControllerDidFinish:(PickerViewController*)viewController;

@end

PickerViewController.m

  #pragma mark -
#pragma mark picker view methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
{
    return 3;
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    if (component == 0)
    {
        NSLog(@"you selected %@", [array1 objectAtIndex:row]);

    }

    if (component == 1)
    {
        NSLog(@"you selected %@", [array2 objectAtIndex:row]);

    }


    if (component == 2)
    {
        NSLog(@"you selected %@", [array3 objectAtIndex:row]);

    }




}




- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
{




    if (component == 0)
    {
        return [array1 count];
    }

    if (component == 1)
    {
        return [array2 count];
    }


    if (component == 2)
    {
        return [array3 count];
    }

    else
    {
        return [array1 count];
    }
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
{

    if (component == 0)
    {
        return [array1 objectAtIndex:row];
    }

    if (component == 1)
    {
        return [array2 objectAtIndex:row];
    }

    if (component == 2)
    {
        return [array3 objectAtIndex:row];
    }

    else
    {
        return [array2 objectAtIndex:row];
    }
}



- (void)populateArray1
{
    array1 = [[NSMutableArray alloc] init];

    [array1 addObject:@"Arthritis"];
    [array1 addObject:@"Cancer"];
    [array1 addObject:@"HIV"];
    [array1 addObject:@"Migraines"];
    [array1 addObject:@"Insomnia"];

}

- (void)populateArray2
{
    array2 = [[NSMutableArray alloc] init];

    [array2 addObject:@"Nausea"];
    [array2 addObject:@"Pain"];
    [array2 addObject:@"Appetite"];
    [array2 addObject:@"Fever"];
    [array2 addObject:@"Exhaustion"];

}

- (void)populateArray3
{
    array3 = [[NSMutableArray alloc] init];

    [array3 addObject:@"Oil"];
    [array3 addObject:@"Plant"];
    [array3 addObject:@"Edible"];
    [array3 addObject:@"Powder"];


}



- (IBAction)buttonpressed:(UIButton *)sender {

        NSLog(@"Button Pushed!");

}



- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Make sure your segue name in storyboard is the same as this line
    if ([[segue identifier] isEqualToString:@"pickerGo"])
    {
        // Get reference to the destination view controller
        ViewController *strainTableView = [(UINavigationController *)[segue destinationViewController] topViewController];

        NSPredicate *ailmentPredicate = [NSPredicate predicateWithFormat:@"Ailment contains[cd] %@", [pickerView selectedRowInComponent:0]];

        NSPredicate *actionPredicate = [NSPredicate predicateWithFormat:@"Action contains[cd] %@", [pickerView selectedRowInComponent:1]];

        NSPredicate *ingestPredicate = [NSPredicate predicateWithFormat:@"Ingestion contains[cd] %@", [pickerView selectedRowInComponent:2]];


        NSCompoundPredicate *resultPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects: ailmentPredicate,actionPredicate,ingestPredicate, nil]];

        searchResults = [Strains filteredArrayUsingPredicate:resultPredicate];

        // Pass any objects to the view controller here, like...
        [strainTableView setSearchResults: searchResults];
    }
}
Brittany L
  • 131
  • 1
  • 13
  • First can you log the searchText and the searchResults to make sure the issue is within the method filterContentForSearchText especially the filteredArrayUsingPredicate method? – Valent Richie May 23 '13 at 02:44
  • The searchText and filterContentForSearchText is attached to a SearchBar inside the uiTableView, not to the UiPickerView. The actual SearchBar works just fine :) It's the filtering of the uitableview with the UiPickerView component upon clicking my "Go" button that isn't working at all. – Brittany L May 23 '13 at 03:11

2 Answers2

0

Very puzzling, your code actually seems ok to me. I'd start by NSLoging searchResults right after the searchResults = [Strains filteredArrayUsingPredicate:resultPredicate]; line is fired, just in case something funny is happening in the table view delegates.

You should also probably check out the free Sensible TableView framework, as it provides automatic searching and filtering for your data. Should save you a ton of time.

Matt
  • 2,391
  • 2
  • 17
  • 18
  • *Note: Something funny is definitely happening in my TableView. So I NSlogged it, like so: if (tableView == self.searchDisplayController.searchResultsTableView) { NSLog(@"Using the search results"); cell.titleLabel.text = [[searchResults objectAtIndex:indexPath.row] objectForKey:@"Title"]; and on the full list, I used: } else { NSLog(@"Using the FULL LIST!!"); cell.titleLabel.text = [[Strains objectAtIndex:indexPath.row] objectForKey:@"Title"]; Console says it's using the full list! Argh. How do I get it to use the correct view? See code updated above. – Brittany L May 29 '13 at 01:06
0

It seems your Strains array contains dictionaries. So you should decide on what key you want to filter, for example the Title key, instead of using SELF:

NSPredicate *resultPredicate = [NSPredicate 
                                predicateWithFormat:@"Title contains[cd] %@",
                                searchText];

From the pickerViewController, you need to go back to the tableViewController. You can use delegate. And try to make a separate function in the table view controller to filter which contains the predicate:

- (void)filterContentForPicker:(NSString*)searchText
{
    NSPredicate *resultPredicate = [NSPredicate
                                    predicateWithFormat:@"Title contains[cd] %@",
                                    searchText];

    searchResults = [Strains filteredArrayUsingPredicate:resultPredicate];
    [self.tableView reloadData]
}
Valent Richie
  • 5,226
  • 1
  • 20
  • 21
  • I'm not using searchText to filter though, I'm using the selected Pickerview component? I did choose which keys to filter with each component? – Brittany L May 23 '13 at 03:35
  • Then from your picker view `didSelectRow` you need to call the `filterContentForSearchText` method. – Valent Richie May 23 '13 at 03:41
  • If I put that method into the pickerview, how would I alter this code to make it work, as it's not using a search bar? -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { [self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]]; return YES;} – Brittany L May 23 '13 at 04:03
  • You should not copy the method to picker view, instead the picker view should pass the selected option to the table view controller, and table view controller should filter the rows based on the passed option. – Valent Richie May 23 '13 at 04:23
  • I see; so I'm missing the bit where the pickerview passes the selected value to the table view controller. Can you show me what that code would look like? Never encountered this before lol. Totally appreciate your help, this is driving me up the walls! :) – Brittany L May 23 '13 at 04:30
  • take a look here: http://stackoverflow.com/questions/6168919/how-do-i-set-up-a-simple-delegate-to-communicate-between-two-view-controllers and let me know if you still encounter issues :) – Valent Richie May 23 '13 at 05:18
  • Hey there :) So I took a peek at the example, and I think I've implemented the majority of it correctly! See my updated code above. I'm just a little unsure as to how I should implement the last little bit in my TableViewController.m file? Thanks so much for your help! – Brittany L May 26 '13 at 00:12