NSPredicate not filtering UITableView? - objective-c

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];
}
}

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.

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]
}

Related

How to show UISearchbar bar only in tableview not on UINavigationbar in objective c

I am new in ios and I am facing problem regarding to UISearchbar. I have done code like this
.h
IBOutlet UITableView *table;
NSArray *recipes;
NSArray *searchResults;
.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
recipes = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", #"Hamburger", #"Ham and Egg Sandwich", #"Creme Brelee", #"White Chocolate Donut", #"Starbucks Coffee", #"Vegetable Curry", #"Instant Noodle with Egg", #"Noodle with BBQ Pork", #"Japanese Noodle with Pork", #"Green Tea", #"Thai Shrimp Cake", #"Angry Birds Cake", #"Ham and Cheese Panini", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return [recipes count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
}
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
But it shows me search bar on navigation bar
But I need to show it on the UItableView itself. Like this in Image
Thanks in advance
I have use code to search from 4 mutable array...
- (void)viewDidLoad {
[super viewDidLoad];
[searchtxt addTarget:self action:#selector(textFieldDidChangeClose:) forControlEvents:UIControlEventEditingChanged];
searchtxt.delegate=self;
}
#pragma mark - Seach Button...
-(void)textFieldDidChangeClose:(UITextField *)textField
{
searchTextString=textField.text;
[self updateSearchArray:searchTextString];
}
-(void)updateSearchArray:(NSString *)searchText
{
if(searchText.length==0)
{
isFilter=NO;
[table reloadData];
}
else{
isFilter=YES;
searchArray=[[NSMutableArray alloc]init];
searchArrayId=[[NSMutableArray alloc] init];
searchArraystatus=[[NSMutableArray alloc] init];
searchArraydescription=[[NSMutableArray alloc] init];
for(NSString *string in idarray){
NSRange stringRange=[string rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(stringRange.location !=NSNotFound){
[searchArray addObject:string];
NSInteger index = [idarray indexOfObject:string];
[searchArraystatus addObject:[shortnamearray objectAtIndex:index]];
[searchArraydescription addObject:[descarray objectAtIndex:index]];
[searchArrayId addObject:[complaintidArray objectAtIndex:index]];
}
}
[table reloadData];
}
}
#pragma mark - TableView Delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(isFilter)
{
return [searchArray count];
}
else
{
return [idarray count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *STI=#"STI";
IBTClosedComplaintCell *cell = (IBTClosedComplaintCell *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:STI];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"IBTClosedComplaintCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.accessoryType=UITableViewCellAccessoryNone;
}
if(isFilter)
{
cell.Complaintnamelbl.text=[NSString stringWithFormat:#"%#",[searchArray objectAtIndex:indexPath.row]];
cell.statuslbl.text = [NSString stringWithFormat:#"%#",[searchArraystatus objectAtIndex:indexPath.row]];
cell.descriptiolbl.text=[NSString stringWithFormat:#"%#",[searchArraydescription objectAtIndex:indexPath.row]];
cell.complaintidlbl.text = [NSString stringWithFormat:#"%#",[searchArrayId objectAtIndex:indexPath.row]];
}
else
{
cell.Complaintnamelbl.text=[idarray objectAtIndex:indexPath.row];
cell.statuslbl.text=[shortnamearray objectAtIndex:indexPath.row];
cell.descriptiolbl.text=[descarray objectAtIndex:indexPath.row];
cell.complaintidlbl.text=[NSString stringWithFormat:#"%#",[complaintidArray objectAtIndex:indexPath.row]];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
IBTClosedNextScreen *next =[[IBTClosedNextScreen alloc] initWithNibName:#"IBTClosedNextScreen" bundle:nil];
[self.navigationController pushViewController:next animated:YES];
if(isFilter)
{
str1=[NSString stringWithFormat:#"%#",[searchArrayId objectAtIndex:indexPath.row]];
NSLog(#"String =%#",str1);
next.str =str1;
}
else
{
str1=[NSString stringWithFormat:#"%#",[self.complaintidArray objectAtIndex:indexPath.row]];
NSLog(#"String =%#",str1);
next.str =str1;
}
}

SearchBar in UITableView - sorting array issue

I'm trying to integrate search bar with my remote table view but it didn't work properly. There were no errors. I think I did some mistakes but I don't know which part so I need your help.
This is my full code:
//
// MasterViewController.m
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "SDWebImage/UIImageView+WebCache.h"
static NSString *const kConsumerKey = #"a1SNULSPtp4eLQTsTXKKSgXkYB5H4CMFXmleFvqE";
#interface MasterViewController ()<UISearchDisplayDelegate>
#property (nonatomic, assign) NSInteger currentPage;
#property (nonatomic, assign) NSInteger totalPages;
#property (nonatomic, assign) NSInteger totalItems;
#property (nonatomic, assign) NSInteger maxPages;
#property (nonatomic, strong) NSMutableArray *photos;
#property (nonatomic, strong) NSMutableArray *searchResults;
#property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
#end
#implementation MasterViewController
- (void)awakeFromNib {
[super awakeFromNib];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.photos = [NSMutableArray array];
self.searchResults = [NSMutableArray arrayWithCapacity:[self.photos count]];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self loadPhotos:self.currentPage];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.currentPage == self.maxPages
|| self.currentPage == self.totalPages
|| self.currentPage == self.totalPages
|| self.totalItems == self.photos.count) {
return self.photos.count;
}else if(tableView == self.searchDisplayController.searchResultsTableView){
return [self.searchResults count];
}
return self.photos.count + 1;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.currentPage != self.maxPages && indexPath.row == [self.photos count] - 1 ) {
[self loadPhotos:++self.currentPage];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
if (indexPath.row == [self.photos count]) {
cell = [tableView dequeueReusableCellWithIdentifier:#"LoadingCell" forIndexPath:indexPath];
UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *)[cell.contentView viewWithTag:100];
[activityIndicator startAnimating];
}else{
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if(tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
}
NSDictionary *photoItem = self.photos[indexPath.row];
cell.textLabel.text = [photoItem objectForKey:#"name"];
if (![[photoItem objectForKey:#"description"] isEqual:[NSNull null]]) {
cell.detailTextLabel.text = [photoItem objectForKey:#"description"];
}
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:[photoItem objectForKey:#"image_url"]]
placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (error) {
NSLog(#"Error occured : %#", [error description]);
}
}];
}
return cell;
}
#pragma mark UISearchDisplay delegate
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.searchResults removeAllObjects];
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
self.searchResults = [NSMutableArray arrayWithArray:[self.photos filteredArrayUsingPredicate:resultPredicate]];//[self.tableData 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)loadPhotos:(NSInteger)page {
NSString *apiURL = [NSString stringWithFormat:#"https://api.500px.com/v1/photos?feature=editors&page=%ld&consumer_key=%#",(long)page,kConsumerKey];
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:apiURL]
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
if (!error) {
NSError *jsonError = nil;
NSMutableDictionary *jsonObject = (NSMutableDictionary *)[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
NSLog(#"%#",jsonObject);
[self.photos addObjectsFromArray:[jsonObject objectForKey:#"photos"]];
self.currentPage = [[jsonObject objectForKey:#"current_page"] integerValue];
self.totalPages = [[jsonObject objectForKey:#"total_pages"] integerValue];
self.totalItems = [[jsonObject objectForKey:#"total_items"] integerValue];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
}] resume];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DetailViewController *vc = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
vc.StoreList = [_photos objectAtIndex:indexPath.row];
}
#end
NSDictionary *photoItem = self.photos[indexPath.row];
and later
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[cd] %#", searchText];
self.searchResults = [NSMutableArray arrayWithArray:[self.photos filteredArrayUsingPredicate:resultPredicate]];
This looks like u try to sort with predicate not String but Dictionary.
Try :
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF.name contains[c] %#", searchText];
Also i'd recommend u to read this code style and here some tutorial how to implement search
Regarding ur second question
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
if (indexPath.row == [self.photos count]) {
cell = [tableView dequeueReusableCellWithIdentifier:#"LoadingCell" forIndexPath:indexPath];
UIActivityIndicatorView *activityIndicator = (UIActivityIndicatorView *)[cell.contentView viewWithTag:100];
[activityIndicator startAnimating];
} else{
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if(tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [self.searchResults[indexPath.row] valueForKey:#"name"] } else {
NSDictionary *photoItem = self.photos[indexPath.row];
cell.textLabel.text = [photoItem objectForKey:#"name"];
if (![[photoItem objectForKey:#"description"] isEqual:[NSNull null]]) {
cell.detailTextLabel.text = [photoItem objectForKey:#"description"];
}
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:[photoItem objectForKey:#"image_url"]]
placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (error) {
NSLog(#"Error occured : %#", [error description]);
}
}];
}
}
return cell;
}

Uncheck (unfavorite) items in Favorites Table View

I have a tableview that displays a list of "favorited" items. Users favorite items in another tableview, and favorited items are listed in this tableview (FavoritesTableView.m).
For some reason, I can't get checked items (favorited items) to "uncheck" from the FavoritesTableView? What am I missing?
See the .m file below...
FavoritesViewController.h
#import <UIKit/UIKit.h>
#import "StrainTableCell.h"
#interface FavoritesViewController : UITableViewController
{
}
#property (strong, nonatomic) NSArray *favoritesArrayset;
#property (strong, nonatomic) IBOutlet UITableView *favoritesTable;
#property (nonatomic, strong) NSMutableArray * favoritesArray;
- (IBAction)backbuttonpressed: (UIBarButtonItem *)sender;
#end
FavoritesViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
if (favoritesArray == Nil)
{
favoritesArray = [[NSMutableArray alloc] init];
}
else
{
[favoritesArray removeAllObjects];
}
NSData *dataSave = [[NSUserDefaults standardUserDefaults] objectForKey:#"strains"];
if (dataSave != Nil)
{
favoritesArrayset = [NSKeyedUnarchiver unarchiveObjectWithData:dataSave];
for (NSDictionary *item in favoritesArrayset)
{
BOOL isChecked = [[item objectForKey:#"checked"] boolValue];
if (isChecked == YES )
{
[favoritesArray addObject:item];
}
}
}
[favoritesTable reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return favoritesArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *Strains = [favoritesArray copy];
NSArray *dataArray = [favoritesArray copy];
static NSString *strainTableIdentifier = #"StrainTableCell";
StrainTableCell *cell = (StrainTableCell *)[tableView dequeueReusableCellWithIdentifier:strainTableIdentifier];
if (cell == nil)
{
cell = [[StrainTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strainTableIdentifier] ;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"StrainTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
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"];
cell.whatCellamI = [NSNumber numberWithInt:indexPath.row];
NSMutableDictionary *item = [dataArray objectAtIndex:indexPath.row];
cell.textLabel.text = [item objectForKey:#"text"];
[item setObject:cell forKey:#"StrainTableCell"];
}
BOOL checked = [[item objectForKey:#"checked"] boolValue];
UIImage *image = (checked) ? [UIImage imageNamed:#"checked.png"] : [UIImage imageNamed:#"unchecked.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
button.frame = frame;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button addTarget:self action:#selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
StrainDetailViewController *detailViewController = [[StrainDetailViewController alloc]
initWithNibName:#"StrainDetailViewController" bundle:nil];
detailViewController.title = [[favoritesArray objectAtIndex:indexPath.row] objectForKey:#"Title"];
detailViewController.strainDetail = [favoritesArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 82;
}
- (IBAction)backbuttonpressed:(id)sender
{
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
}
- (void)checkButtonTapped:(id)sender event:(id)event
{
NSLog(#"made it here and event is %#",event);
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.favoritesTable];
NSIndexPath * indexPath ;
indexPath = [self.favoritesTable indexPathForRowAtPoint: currentTouchPosition];
NSLog(#"indexpath is below");
NSLog(#"%#",indexPath);
if (indexPath != Nil)
{
NSMutableDictionary *item = [favoritesArray objectAtIndex:indexPath.row];
BOOL isItChecked = [[item objectForKey:#"checked"] boolValue];
/*
if (isItChecked == NO) {
NSMutableArray *tmpArray = [[NSMutableArray alloc] init];
NSMutableArray *tmpArray2 = [[NSMutableArray alloc] initWithArray:[favoritesArray allObjects]];
NSString *text1 = [item objectForKey:#"Title"];
for (NSDictionary * object in tmpArray2) {
NSString *text2 = [object objectForKey:#"Title"];
if (![text1 isEqualToString:text2]) {
[tmpArray addObject:object];
}
}
// [favoritesArray removeAllObjects];
favoritesArray = [tmpArray copy];
}
*/
NSMutableArray *quickArray = [[NSMutableArray alloc] initWithArray:favoritesArray];
[quickArray replaceObjectAtIndex:indexPath.row withObject:item];
[item setObject:[NSNumber numberWithBool:!isItChecked] forKey:#"checked"];
favoritesArray = [quickArray copy];
// [self.favoritesArray addObject:item];
// NSLog(#"you have added %d items to favorites", self.favoritesArray.count);
[favoritesTable reloadData];
}
#end
In your .h take one NSMutableDictionary and do property to it.
In your .m synthesize it,and in viewdidLoad alloc the Dictionary.
Now put this below code in CellForRowAtIndex
if([idDictonary objectForKey:[NSString stringWithFormat:#"%d",[indexPath row]]])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
and put this below code in DidSelectRowAtIndex
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if (thisCell.accessoryType == UITableViewCellAccessoryNone)
{
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
[idDictonary setValue:[dataArray objectAtIndex:indexPath.row] forKey:[NSString stringWithFormat:#"%d",[indexPath row]]];
}
else
{
if([idDictonary objectForKey:[NSString stringWithFormat:#"%d",[indexPath row]]])
{
[idDictonary removeObjectForKey:[NSString stringWithFormat:#"%d",[indexPath row]]];
thisCell.accessoryType = UITableViewCellAccessoryNone;
}
}
[myTableView reloadData];
NSLog(#"idDictonary = %#",idDictonary);
i hope this will helps u Brittany...
Every time -tableView:cellForRowAtIndexPath: runs, you create a new button, set it to the desired properties and … throw it away. (Seems to be the running joke this week.) You have to use the existing button.

Filtered array returns empty, and I'm not sure why?

I'm using a PickerView to filter an existing array (called "Strains"), and the filtered array is called, "searchResults". Not sure why, but for some reason my app is saying that searchResults is empty (even though Strains is successfully populating). The crash error I get like this:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array
Any idea as to why? Code below. Note: 'Strains' is being pulled from a MySQL database.
PickerViewController.m
- (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];
}
}
- (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];
}
}
- (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"];
}
if ([[segue identifier] isEqualToString:#"pickerGo"])
{
NSLog(#"%#", Strains);
// Get reference to the destination view controller
PickerResultsTableViewController *PickerTableView = [(UINavigationController *)[segue destinationViewController] topViewController];
NSLog(#"%#", PickerTableView);
NSPredicate *ailmentPredicate = [NSPredicate predicateWithFormat:#"Ailment CONTAINS[c] %#", [array1 objectAtIndex:[pickerView selectedRowInComponent:0]]];
NSPredicate *actionPredicate = [NSPredicate predicateWithFormat:#"Action CONTAINS[c] %#", [array2 objectAtIndex:[pickerView selectedRowInComponent:1]]];
NSPredicate *ingestPredicate = [NSPredicate predicateWithFormat:#"Ingestion CONTAINS[c] %#", [array3 objectAtIndex:[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...
[PickerTableView setSearchResults: [searchResults copy]];
NSLog(#"%#", searchResults);
}
}
TableViewController.m
- (int)numberOfSectionsInTableView: (UITableView *)tableview
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == PickerTableView) {
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 == strainTableView) {
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);
This code:
else
{
return [array2 objectAtIndex:row];
}
Should never be run, but if it is could break because the count uses array1 and here you use array2.
For your predicates, selectedRowInComponent: returns an integer, but you're trying to use it like it returns an object. I'm guessing you want something more like:
NSPredicate *ailmentPredicate = [NSPredicate predicateWithFormat:#"Ailment CONTAINS[c] %#", [array1 objectAtIndex:[pickerView selectedRowInComponent:0]]];
...
(Assuming that your Strain objects have a property called Ailment, and that you always have > 0 objects in array1).
Wherever the crash is you should be checking the count of the array before trying to use it.
[PickerTableView setSearchResults: searchResults];
may be causing the trouble .It becomes deallocated when the next scene is loaded
make a copy of searchResults and use it
[PickerTableView setSearchResults: [searchResults copy]];
Note:Implement copyWithZone: if You use customObjects in the array

For some reason, NSPredicate is not filtering my UITableView?

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:#"SELF contains[cd] %#",
searchText];
searchResults = [Strains filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[se
lf 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];
}
- (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
#implementation PickerViewController
- (void)handleCloseButton:(id)sender {
if ([self.delegate respondsToSelector:#selector(PickerViewControllerDidFinish:)]) {
[self.delegate PickerViewControllerDidFinish:self];
}
}
#synthesize pickerView;
#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"];
}
- (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];
}
}
Your predicate:
NSPredicate *resultPredicate =
[NSPredicate predicateWithFormat:#"SELF contains[cd] %#", searchText];
searchResults = [Strains filteredArrayUsingPredicate:resultPredicate];
Looks to be trying to use "Strain" objects (which you haven't given a definition of but which are definitely compound objects) as string objects.
CONTAINS[cd] is a string comparison function.
Define your predicate more like the compound version you're using for the picker.