Parse search table not returning correct results - objective-c

I am using parse as back-end for my app. I have found a few different methods to implement searchbar feature using a Parse tableview. This idea I found from Parse archives shows all objects on initial view and refresh, but when I search it does not return the correct results. If I type one letter "a" it returns some objects containing "a" but if I type more letters or and actual word that I know should be found it returns a blank table. It is also giving a warning when searching: A long-running Parse operation is being executed on the main thread. I have been working and researching this for a few weeks and can't get past this point. See code for implementation file.
#import "RecipeBookViewController.h"
#import "SearchedResultCell.h"
#import "RecipeDetailViewController.h"
#import "HotelViewController.h"
#import "Recipe.h"
static NSString *const NothingFoundCellIdentifier = #"NothingFoundCell";
#interface RecipeBookViewController ()
#end
#implementation RecipeBookViewController {
}
#synthesize searchedBar;
#synthesize searchResults;
#synthesize recipesTable;
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// Custom the table
// The className to query on
self.parseClassName = #"Recipe";
// The key of the PFObject to display in the label of the default cell style
self.textKey = #"name";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = NO;
// The number of objects to show per page
//self.objectsPerPage = 10;
}
return self;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - UIViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UINib *cellNib = [UINib nibWithNibName:NothingFoundCellIdentifier bundle:nil];
[self.tableView registerNib:cellNib forCellReuseIdentifier:NothingFoundCellIdentifier];
[self.searchedBar becomeFirstResponder];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshTable:)
name:#"refreshTable"
object:nil];
}
- (void)refreshTable:(NSNotification *) notification
{
// Reload the recipes
[self loadObjects];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"refreshTable" object:nil];
}
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchResults removeAllObjects];
[self.searchedBar resignFirstResponder];
searchResults = [NSMutableArray arrayWithCapacity:10];
//#warning Put your ClassName here
PFQuery *query = [PFQuery queryWithClassName:#"Recipe"];
//#warning put key that you want to search here
[query whereKey:#"name" containsString:searchedBar.text];
NSArray *results = [query findObjects];
[searchResults addObjectsFromArray:results];
//#warning put your key here
[query orderByAscending:#"name"];
//[self queryForTable];
[self loadObjects];
}
#pragma mark - PFQueryTableViewController
- (void)objectsWillLoad {
[super objectsWillLoad];
// This method is called before a PFQuery is fired to get more objects
}
- (void) objectsDidLoad:(NSError *)error
{
[super objectsDidLoad:error];
NSLog(#"error: %#", [error localizedDescription]);
}
#pragma mark - Query
- (PFQuery *)queryForTable
{
PFQuery *query;
if (self.searchResults == 0) {
query = [PFQuery queryWithClassName:self.parseClassName];
} else {
query = [PFQuery queryWithClassName:self.parseClassName];
NSString *searchThis = [searchedBar.text lowercaseString];
//#warning key you wanted to search here
[query whereKeyExists:#"name"];
[query whereKey:#"name" containsString:searchThis];
}
[query orderByAscending:#"name"];
// If Pull To Refresh is enabled, query against the network by default.
if (self.pullToRefreshEnabled) {
query.cachePolicy = kPFCachePolicyNetworkOnly;
}
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
if (self.objects.count == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
return query;
}
/*
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
if (searchResults == nil) {
return 0;
} else if ([searchResults count] == 0) {
return 1;
} else {
return [self.objects count];
}
}
*/
// Override to customize the look of a cell representing an object. The default is to display
// a UITableViewCellStyleDefault style cell with the label being the first key in the object.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"RecipeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:#"recipeBoxImage2.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:#"name"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:#"prepTime"];
static NSString *LoadMoreCellIdentifier = #"LoadMoreCell";
UITableViewCell *loadcell = [self.tableView dequeueReusableCellWithIdentifier:LoadMoreCellIdentifier];
if (!cell) {
loadcell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:LoadMoreCellIdentifier];
}
return cell;
}
- (void)configureSearchResult:(SearchedResultCell *)cell atIndexPath: (NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"RecipeCell";
SearchedResultCell *searchcell = [self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (searchcell == nil) {
searchcell = [[SearchedResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:#"recipeBoxImage2.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:#"name"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:#"prepTime"];
}
// Set CellForRowAtIndexPath
- (UITableViewCell *)searchtableView:(UITableView *)searchtableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *CellIdentifier = #"SearchResultCell";
//Custom Cell
SearchedResultCell *cell = [searchtableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[SearchedResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if ([searchResults count] == 0) {
//cell.mainTitle.text = #"Nothing Found";
return [self.tableView dequeueReusableCellWithIdentifier:NothingFoundCellIdentifier];
} else {
//#warning put your ClassName here
PFObject *object = [PFObject objectWithClassName:#"Recipe"];
object = [searchResults objectAtIndex:indexPath.row];
[self configureSearchResult:cell atIndexPath:indexPath object:object];
//[self configureSearchResult:cell atIndexPath:indexPath object:object];
return cell;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForNextPageAtIndexPath:(NSIndexPath *)indexPath {
static NSString *LoadMoreCellIdentifier = #"LoadMoreCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LoadMoreCellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:LoadMoreCellIdentifier];
}
return cell;
}
//// Set TableView Height for Load Next Page
//- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath {
// if([self.objects count] == indexPath.row) {
// // Load More Cell Height
// return 60.0;
// } else {
// return 80.0;
// }
//}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[searchedBar resignFirstResponder];
if ([self.objects count] == indexPath.row) {
[self loadNextPage];
} else {
PFObject *photo = [self.objects objectAtIndex:indexPath.row];
NSLog(#"%#", photo);
// Do something you want after selected the cell
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.searchedBar resignFirstResponder];
}
//- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
//{
// // Remove the row from data model
// PFObject *object = [self.objects objectAtIndex:indexPath.row];
// [object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
// [self refreshTable:nil];
// }];
//}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
Recipe *recipe = [[Recipe alloc] init];
recipe.name = [object objectForKey:#"name"];
recipe.imageFile = [object objectForKey:#"imageFile"];
recipe.prepTime = [object objectForKey:#"prepTime"];
recipe.ingredients = [object objectForKey:#"ingredients"];
recipe.instructions = [object objectForKey:#"instructions"];
recipe.servings = [object objectForKey:#"servings"];
recipe.hotelSite = [object objectForKey:#"hotelSite"];
recipe.recipeType = [object objectForKey:#"recipeType"];
destViewController.recipe = recipe;
}
}
#end

found this - hope it helps others - credit to Bizzi-Body
https://github.com/Bizzi-Body/ParseTutorial-Part-2
//
// GourmetChefViewController.m
//
// Created by RedMac on 3/19/15.
//
#import "RecipeBookViewController.h"
#interface RecipeBookViewController ()
{
NSMutableArray *totalStrings;
NSMutableArray *filteredStrings;
BOOL isFiltered;
}
#end
#implementation RecipeBookViewController
#pragma mark -
#pragma mark UIViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
self.mySearchBar.delegate =self;
self.myTableView.delegate = self;
self.myTableView.dataSource=self;
[self retrieveFromParse];
}
- (void) retrieveFromParse {
PFQuery *retrieveRecipes = [PFQuery queryWithClassName:#"Recipe"];
[retrieveRecipes whereKeyExists:#"name"];
[retrieveRecipes findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSLog(#"%#", objects);
totalStrings = [[NSMutableArray alloc] initWithArray:objects];
}
[self.myTableView reloadData];
}];
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *) searchText{
if (searchText.length ==0){
isFiltered =NO;}
else{
isFiltered =YES;
filteredStrings=[[NSMutableArray alloc]init];
for(PFObject *element in totalStrings) {
NSString * str = [element objectForKey:#"name"];
NSLog(#"%#", NSStringFromClass([element class])); // you thought that totalStrings
// contained NSString objects,
// but it contains PFObjects.
NSRange stringRange =[str rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (stringRange.location !=NSNotFound) {
// you need to add the PFObject back to make your cellForRowAtIndexPath: method
// work.
[filteredStrings addObject:element]; // used to be :str
}
}
}
[self.myTableView reloadData];
}
//table view datasource and delegate method.....
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section
{
if (isFiltered){
return [filteredStrings count];
}return [totalStrings count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"RecipeCell";
UITableViewCell *cell= [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (!cell){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if(!isFiltered){
PFObject *tempObject =[totalStrings objectAtIndex: indexPath.row];
cell.textLabel.text = [tempObject objectForKey:#"name"];
}
else
{
PFObject *tempObject2 =[filteredStrings objectAtIndex: indexPath.row];
cell.textLabel.text =[tempObject2 objectForKey:#"name"];
}
return cell;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end

Related

Objective-C syntax error - unexpected "#" / unable to fix problems

enter code here[youtube picture of the same code][1]I keep getting an error with my code where it says
"unexpected "#" in program and also missing "#end"
If you look at the code below the #end is there but however much I retype it the answer is the same "missing #end"
Here is the full code
#import "MasterViewController.h"
#import "DetailViewController.h"
#interface MasterViewController ()
#end
#implementation MasterViewController
-(NSMutableArray *) objects
{
if (!_objects){
_objects =[[NSMutableArray alloc]init];
}
return _objects;
}
-(NSMutableArray *) results
{
if (!_results) {
_results =[[NSMutableArray alloc]init];
}
return _results;
}
-(void)viewDidLoad
{
[super viewDidLoad];
[self.objects addObject:#"Tabebuia yellow"];
[self.objects addObject:#"Prunus armeniaca"];
[self.objects addObject:#"Tabebuia rosea"];
}
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) searchThroughData
{
self.results= nil;
NSPredicate * resultsPredicate = [NSPredicate predicateWithFormat:#"SELF contains [search]%#", self.searchBar.text];
self. results = [[ self.objects filteredArrayUsingPredicate:resultsPredicate]mutableCopy];
}
-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[self searchThroughData];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.tableView)
{
return self.objects.count;
}else{
[self searchThroughData];
return self.results.count;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (tableView == self.tableView){
cell.textLabel.text = self.objects[indexPath.row];
} else {
cell.textLabel.text = self.results[indexPath.row];
}
return cell;
}
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (self.searchController.isActive)
{
[self performSegueWithIdentifier:#"Showdetail" sender:self];
}
-(void) PrepareForSegue:(UIStoryboardSegue *) segue sender:(id) sender
if ([[ segue identifier] isEqualToString:#"ShowDetail"]) {
NSString *object = nil;
NSIndexPath *Indexpath = nil;
if (self.UISearchController.isActive)
{UISearchController
Indexpath = [[ self.searchController searchResultsTableView]indexPathForSelectedRow];
object = self.results [Indexpath.row];
}else{
Indexpath = [self.tableView indexPathForSelectedRow];
object = [[self.objects [Indexpath.row];
[segue destinationViewController] setDetailLabelContents:object];
}}
#end
You have no closing } at the end of the prepareForSegue:sender: method. Formatting and indenting properly makes this clear.
You have code just floating outside of a method (the lines before the tableView:didSelectRowAtIndexPath: method.
There needs to be a proper pairing of { and } and code needs to be inside methods or functions.

Search bar in tableview using objective c with parse database

I've been following a tutorial teaching how to make a tableview with a search bar. I got this to work without problems, but now I learned to make the same tableview but instead of local arrays, I've been getting my data from parse as PFObjects.
I then tried to take the search bar and implant it in my new tableview which uses parse. I can't get this to work. Following the tutorial with the search bar they are using simple arrays stored locally..
Can anyone point me in the right direction of how to use a search bar in a tableview that gets its data from a parse database?
This is my code that works with my tableview that does NOT use parse.
#implementation RecipeBookViewController {
NSArray *recipes;
NSArray *searchResults;
}
#synthesize tableView = _tableView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Initialize table data
recipes = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto",
#"Full Breakfast", #"Hamburger", #"Ham and Egg Sandwich", #"Creme Brelee",
nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (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 *simpleTableIdentifier = #"RecipeCell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath
- *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
[self performSegueWithIdentifier: #"showRecipeDetail" sender: self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
RecipeDetailViewController *destViewController =
segue.destinationViewController;
NSIndexPath *indexPath = nil;
if ([self.searchDisplayController isActive]) {
indexPath = [self.searchDisplayController.searchResultsTableView
indexPathForSelectedRow];
destViewController.recipeName = [searchResults
objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
destViewController.recipeName = [recipes objectAtIndex:indexPath.row];
}
}
}
- (void)filterContentForSearchText:(NSString*)searchText scope:
(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
#pragma mark - UISearchDisplayController delegate methods
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar
scopeButtonTitles]
objectAtIndex:
[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
And this is my tableview which get its data from my parse database:
#implementation RecipeBookViewController {
}
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// Custom the table
// The className to query on
self.parseClassName = #"Recipe";
// The key of the PFObject to display in the label of the default cell
style
self.textKey = #"name";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = NO;
// The number of objects to show per page
//self.objectsPerPage = 10;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshTable:)
name:#"refreshTable"
object:nil];
}
- (void)refreshTable:(NSNotification *) notification
{
// Reload the recipes
[self loadObjects];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"refreshTable"
object:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
// If no objects are loaded in memory, we look to the cache first
to fill the table
// and then subsequently do a query against the network.
/* if ([self.objects count] == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}*/
// [query orderByAscending:#"name"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:
(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"RecipeCell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:#"placeholder.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:#"name"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:#"prepTime"];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:
(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath*) indexPath
{
// Remove the row from data model
PFObject *object = [self.objects objectAtIndex:indexPath.row];
[object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
[self refreshTable:nil];
}];
}
- (void) objectsDidLoad:(NSError *)error
{
[super objectsDidLoad:error];
NSLog(#"error: %#", [error localizedDescription]);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController =
segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
Recipe *recipe = [[Recipe alloc] init];
recipe.name = [object objectForKey:#"name"];
recipe.imageFile = [object objectForKey:#"imageFile"];
recipe.prepTime = [object objectForKey:#"prepTime"];
recipe.ingredients = [object objectForKey:#"ingredients"];
destViewController.recipe = recipe;
}
}

Problems Implementing Search Bar with Parse Data

I have searched the land of Google far and wide and I have found tutorials on this, but they are before IOS8. I have tried to piece this together as best as I can, but yet when the app runs, and I type words into the search bar, nothing returns, or it crashes. So here's how the view looks, and what each object means:
Here is my JobListViewController.m File:
#import "JobDetailViewController.h"
#import "JobListViewController.h"
#import "Job.h"
#import "SearchedResultCell.h"
#interface JobListViewController () <UISearchDisplayDelegate, UISearchBarDelegate> {
}
#property (nonatomic, weak) IBOutlet UISearchBar *searchedBar;
#property (nonatomic, strong) NSString *mainTitle;
#property (nonatomic, strong) NSString *subTitle;
#property (nonatomic, assign) BOOL canSearch;
#end
#interface JobListViewController ()
#end
#implementation JobListViewController
{
NSArray *jobs;
NSArray *searchResults;
}
#synthesize searchedBar;
#synthesize mainTitle;
#synthesize subTitle;
#synthesize canSearch;
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// Custom the table
// The className to query on
self.parseClassName = #"Jobs";
// The key of the PFObject to display in the label of the default cell style
self.textKey = #"Position";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = YES;
// The number of objects to show per page
self.objectsPerPage = 10;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.searchedBar becomeFirstResponder];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.canSearch = 0;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)objectsWillLoad {
[super objectsWillLoad];
// This method is called before a PFQuery is fired to get more objects
}
- (PFQuery *)queryForTable
{
PFQuery *query;
if (self.canSearch == 0)
{
query = [PFQuery queryWithClassName:#"Jobs"];
}
else
{
query = [PFQuery queryWithClassName:#"Jobs"];
NSString *searchThis = [searchedBar.text uppercaseString];
[query whereKey:#"Position" containsString:searchThis];
}
[query orderByAscending:#"Position"];
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object: (PFObject *)object
{
static NSString *simpleTableIdentifier = #"JobCell";
static NSString *pimpleTableIdentifier = #"JobCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
SearchedResultCell *cell = [self.tableView dequeueReusableCellWithIdentifier:pimpleTableIdentifier];
if (cell == nil) {
cell = [[SearchedResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:pimpleTableIdentifier];
}
[self configureSearchResult:cell atIndexPath:indexPath object:object];
}
// Configure the cell
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:#"placeholder.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *positionLabel = (UILabel*) [cell viewWithTag:101];
positionLabel.text = [object objectForKey:#"Position"];
UILabel *rotationLabel = (UILabel*) [cell viewWithTag:102];
rotationLabel.text = [object objectForKey:#"Rotation"];
UILabel *locationLabel = (UILabel*) [cell viewWithTag:103];
locationLabel.text = [object objectForKey:#"Location"];
UILabel *typeLabel = (UILabel*) [cell viewWithTag:104];
typeLabel.text = [object objectForKey:#"Type"];
return cell;
}
- (void) objectsDidLoad:(NSError *)error
{
[super objectsDidLoad:error];
NSLog(#"error: %#", [error localizedDescription]);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showJobDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Job *job = [[Job alloc] init];
JobDetailViewController *destViewController = segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
job.position = [object objectForKey:#"Position"];
job.name = [object objectForKey:#"Name"];
job.email = [object objectForKey:#"Email"];
job.phone = [object objectForKey:#"Phone"];
job.imageFile = [object objectForKey:#"imageFile"];
job.rotation = [object objectForKey:#"Rotation"];
job.location = [object objectForKey:#"Location"];
job.type = [object objectForKey:#"Type"];
job.clearance = [object objectForKey:#"Clearance"];
job.job_description = [object objectForKey:#"Job_Description"];
job.qualifications = [object objectForKey:#"Qualifications"];
destViewController.job = job;
}
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[self clear];
self.canSearch = 1;
[self.searchedBar resignFirstResponder];
[self queryForTable];
[self loadObjects];
}
/*
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (searchResults == nil) {
return 0;
} else if ([searchResults count] == 0) {
return 1;
} else {
return [self.objects count];
}
}
*/
- (void)configureSearchResult:(SearchedResultCell *)cell atIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
mainTitle = [object objectForKey:#"Position"];
cell.mainTitle.text = mainTitle;
subTitle = [object objectForKey:#"Type"];
cell.detail.text = subTitle;
// Implement this if you want to Show image
cell.showImage.image = [UIImage imageNamed:#"placeholder.jpg"];
PFFile *imageFile = [object objectForKey:#"imageFile"];
if (imageFile) {
cell.showImage.file = imageFile;
[cell.showImage loadInBackground];
}
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[searchedBar resignFirstResponder];
if ([self.objects count] == indexPath.row) {
[self loadNextPage];
} else {
PFObject *photo = [self.objects objectAtIndex:indexPath.row];
NSLog(#"%#", photo);
// Do something you want after selected the cell
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.searchedBar resignFirstResponder];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar {
[self.searchedBar resignFirstResponder];
[self queryForTable];
[self loadObjects];
}
#end
I cannot find where I am going wrong. Any help whatsoever would be much appreciated. Or if anything if you can point me in the right direction.
I had problems with that I few months ago, so below is a project that reeeally helped me. Hope for you too.
https://github.com/mwazir2/ParseSearchNoPagination
cheers!
Update
In my adaptation of this example above I followed everything from the project. The project uses PFQueryTableViewController from Parse SDK and not the default iOS TableViewController.
In the first part -(id)initWithCoder I have commented the
//self.textKey = #"username";
Then I altered the - (PFQuery *)queryForTable method in some ways. One just changed the whereKey to adequate my project and the second changed the query a little bit more because it should only show in the table objects related to specific users. Below follows respective queries.
The first more general query
- (PFQuery *)queryForTable
{
PFQuery *query = [PFUser query];
if (self.canSearch == 0) {
query = [PFQuery queryWithClassName:#"_User"];
} else {
query = [PFQuery queryWithClassName:#"_User"];
NSString *searchThis = [searchedBar.text capitalizedString];
//PFQuery *query = [PFQuery queryWithClassName:#"Channel"];
//[query whereKey:#"channelName" equalTo:searchThis];
[query whereKey:#"username" containsString:searchThis];
}
The second, specific to current user:
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
[query whereKey:#"owner" equalTo:[PFUser currentUser]];
[query orderByDescending:#"createdAt"];
if (self.pullToRefreshEnabled) {
query.cachePolicy = kPFCachePolicyNetworkOnly;
}
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
if (self.objects.count == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
return query;
}
For the tableView methods I only used: tableView cellForRowAtIndexPath(pretty much like yours). And also the cellForRowAtIndexPath for the LoadMoreCell, like in the example.
Also the tableView heightForRowAtIndexPath: for the LoadMoreCell and tableView didSelectRowAtIndexPath, like below:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
//[searchedBar resignFirstResponder];
if ([self.objects count] == indexPath.row) {
[self loadNextPage];
} else {
PFObject *photo = [self.objects objectAtIndex:indexPath.row];
NSLog(#"%#", photo);
// Do something you want after selected the cell
}
}
Of course below the } else { statement you can change it or delete the NSLog line.
I suggest you try to alter the example itself with your object and keys, until it works an then alter yours, exactly like the example... :)
Compound Query
PFQuery *query1 = [PFQuery queryWithClassName:#"Class1"];
[name whereKey:#"column1" equalTo:[fieldInCode text]];
PFQuery *query2 = [PFQuery queryWithClassName:#"Class1"];
[enterKey whereKey:#"column2" equalTo:[anotherField text]];
PFQuery *query = [PFQuery orQueryWithSubqueries:#[query1,query2]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
Cheers!

How to add Pagination to Tableview on Search results?

The following lines of code shown below are my current tableview settings. What i would like to achieve is what's seen on the image below.
1) if count is 4 when user scrolls Down show a Activity Indicator and Make a request using the next value shown on the JSON Below.
2) Reload the Table
3) Show No more results if count is empty.
Note: I am new on Objective-C so I will appreciate your guidance on this subject since all searches I have done were not successful on what I am looking to achieve since all of them are based on a table already loaded and not based on a Search Result.
As shown on the Image Below is a reference what i want to achieve.
JSON RESPONSE FROM SEARCH
{
"count": 4,
"next": "http://api.domain.com/user-search/?page=2&subject=culture",
"previous": null,
"results": [
{
"name": "Guillermo Davila",
"nick": "guillermo",
"avatar_s": "https://pbs.twimg.com/profile_images/2213685686/image.jpg",
"user_rate": "$10/h",
"id": 3,
"subjects": "Culture and 1 other subject",
"bio": "I'm a nice person"
},
{
"name": "Frank Smith",
"nick": "fsmith",
"avatar_s": "https://pbs.twimg.com/profile_images/2444486/image.jpg",
"user_rate": "$14/h",
"id": 3,
"subjects": "Culture and 1 other subject",
"bio": "I'm a nice person 2"
}
]
}
And here is my UserTableviewController.h
//
// UserTableViewController.m
// mobile-app
//
// Created by eddwinpaz on 5/18/14.
// Copyright (c) 2014 eddwinpaz. All rights reserved.
//
#import "UserTableViewController.h"
#import "CustomTableCell.h"
#import "UserDetailViewController.h"
#import "AFNetworking.h"
#import "MBProgressHUD.h"
#import "SimpleAudioPlayer.h"
#interface UserTableViewController ()
#end
#implementation UserTableViewController
{
// JSON Request
NSMutableArray *myObject;
// A Dictionary Object
NSDictionary *dictionary;
NSString *name;
NSString *subject;
NSString *avatar;
NSString *rate;
NSString *bio;
NSString *nick;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//[self fetch_tutors]; // Get tutors Ordered By Karma DESC
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
/*
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
} */
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return myObject.count; // This is old 100% working code
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomTableCell";
CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
dictionary = [myObject objectAtIndex:indexPath.row];
cell.labelName.text = [dictionary objectForKey:#"name"];
cell.labelBio.text = [dictionary objectForKey:#"bio"];
cell.labelSubjects.text = [dictionary objectForKey:#"subject"];
cell.imageAvatar.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[dictionary objectForKey:#"avatar"]]]];
cell.imageAvatar.clipsToBounds = YES;
cell.imageAvatar.layer.cornerRadius = cell.imageAvatar.frame.size.width / 2;
cell.labelRate.text = [dictionary objectForKey:#"rate"];
cell.labelRate.layer.cornerRadius = 5;
[SimpleAudioPlayer playFile:#"upvote.wav"];
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showUserDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UserDetailViewController *destViewController = segue.destinationViewController;
NSDictionary *dict = [myObject objectAtIndex:indexPath.row];
destViewController.http_nick = [dict valueForKey:#"nick"];
destViewController.labelName = [dict valueForKey:#"name"];
NSLog(#" Username Sent--->%#", [dict valueForKey:#"nick"]);
NSLog(#" name Sent--->%#", [dict valueForKey:#"name"]);
}
}
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
NSString *searchTerm = searchBar.text;
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeIndeterminate;
hud.labelText = #"Searching Tutors";
[hud show:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *url = [NSString stringWithFormat:#"http://api.domain.com/user-search/?subject=%#",searchTerm];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", responseObject);
[hud hide:YES];
int count_total = [[responseObject objectForKey:#"count"] intValue];
if (count_total == 0) {
[myObject removeAllObjects];
NSLog(#"Count is --->0");
}
else {
myObject = [[NSMutableArray alloc] init];
name = #"name";
subject = #"subject";
avatar = #"avatar";
rate = #"rate";
bio = #"bio";
nick = #"nick";
for (NSDictionary *dataDict in [responseObject objectForKey:#"results"])
{
NSString *name_data = [dataDict objectForKey:#"name"];
NSString *subject_data = [dataDict objectForKey:#"subjects"];
NSString *avatar_data = [dataDict objectForKey:#"avatar_s"];
NSString *rate_data = [dataDict objectForKey:#"user_rate"];
NSString *bio_data = [dataDict objectForKey:#"bio"];
NSString *nick_data = [dataDict objectForKey:#"nick"];
NSLog(#"name: %#", name_data);
NSLog(#"subjects: %#",subject_data);
NSLog(#"avatar_s: %#", avatar_data);
NSLog(#"user_rate: %#",rate_data);
NSLog(#"bio: %#",bio_data);
NSLog(#"nick: %#",nick_data);
dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
name_data,name,
subject_data,subject,
avatar_data,avatar,
rate_data,rate,
bio_data, bio,
nick_data, nick, nil];
[myObject addObject:dictionary];
}
}
[self.searchBar endEditing:YES];
[self.searchBar setShowsCancelButton:NO animated:YES];
[self.searchBar sizeToFit];
[self.tableView reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
[hud hide:YES];
}];
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
[searchBar sizeToFit];
[searchBar setShowsCancelButton:YES animated:YES];
return YES;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
[self.searchBar endEditing:YES];
[searchBar setShowsCancelButton:NO animated:YES];
self.searchBar.text = nil;
}
/*
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"userDetailView"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UserDetailViewController *destViewController = segue.destinationViewController;
destViewController.labelName = [myObject objectAtIndex:indexPath.row];
}
} */
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
One way to achieve it is,
Return the numberOfCells as one more than the data array
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return myDataArray +1 ; //myDataArray is the data and One more cell for the last cell (10 out of 46 results cell)
}
In cellForRowAtIndexPath, if your IndexPath.row == myDataArray.count (ie., Last Row) Create a custom cell which looks as in the picture and return the custom cell.
In - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath, If the indexPath corresponds to last cell, then Start Request for page 2, once the results are fetched, update the myDataArray and reload the table.

Invalid argument type to unary expression

I have this program with a tableView as my first view. I have also implemented (or at least tried to) a search bar on top of the view. Have used several hours to search for a solution, but without positive results.
#import "FirstViewController.h"
#import "NSDictionary-MutableDeepCopy.h"
#implementation FirstViewController
#synthesize listData, table, search, allNames, names, keys;
#pragma mark -
#pragma mark Custom Methods
- (void)resetSearch {
NSMutableDictionary *allNamesCopy = [self.allNames mutableDeepCopy];
self.names = allNamesCopy;
[allNamesCopy release];
NSMutableArray *keyArray = [[NSMutableArray alloc] init];
[keyArray addObjectsFromArray:[[self.allNames allKeys]
sortedArrayUsingSelector:#selector(compare:)]];
self.keys = keyArray;
[keyArray release];
}
-(void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
[self resetSearch];
for (NSString *key in self.keys) {
NSMutableArray *array = [names valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in listData) {
if ([name rangeOfString:searchTerm
options:NSCaseInsensitiveSearch].location == NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
[self.keys removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[table reloadData];
}
- (void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"sortednames" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.names = dict;
self.allNames = dict;
[dict release];
[self resetSearch];
[table reloadData];
[table setContentOffset:CGPointMake(0.0, 44.0)animated:NO];
self.parentViewController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]];
NSArray *array = [[NSArray alloc] initWithObjects:
// A larger amount of objects here.
self.listData = array;
[array release];
[super viewDidLoad];
}
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.listData = nil;
self.table = nil;
self.search = nil;
self.allNames = nil;
self.names = nil;
self.keys = nil;
}
- (void)dealloc {
[listData release];
[search release];
[table release];
[allNames release];
[keys release];
[names release];
[super dealloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return ([keys count] > 0) ? [keys count] : 1;
}
- (NSInteger)tableView:(UITableView *)aTableView
numberOfRowsInSection: (NSInteger)section {
return [self.listData count];
if ([keys count] == 0)
return 0;
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
return [nameSection count];
}
- (UITableViewCell *) extracted_method: (UITableViewCell *) cell {
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)aTableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
static NSString *sectionsTableIdentifier = #"sectionsTableIdentifier";
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:
sectionsTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: sectionsTableIdentifier] autorelease];
}
cell.backgroundColor = [UIColor clearColor];
cell.textColor = [UIColor whiteColor];
cell.detailTextLabel.textColor = [UIColor whiteColor];
cell.text = [nameSection objectAtIndex:row];
[self extracted_method: cell].text = [listData objectAtIndex:row];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section {
if ([keys count] == 0)
return nil;
NSString *key = [keys objectAtIndex:section];
return key;
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return keys;
}
#pragma mark -
#pragma mark Table View Delegate Methods
- (NSIndexPath *)tableView:(UITableView *)tableView
willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[search resignFirstResponder];
return indexPath;
}
#pragma mark -
#pragma mark Search Bar Delegate Methods
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSString *searchTerm = [searchBar text];
[self handleSearchForTerm:searchTerm];
}
- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchTerm {
if ([searchTerm length] == 0) {
[self resetSearch];
[table reloadData];
return;
}
[self handleSearchForTerm:searchTerm];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
search.text = #"";
[self resetSearch];
[table reloadData];
[searchBar resignFirstResponder];
}
#end
Ok guys. My problem is that this doesnt get the search function to work. In addition I receive siginal SIGABRT at this line:
NSString *key = [keys objectAtIndex:section];
So I need help with two things:
1: I need to get that SIGABRT away.
Error log message: * Terminating app due to uncaught exception
'NSRangeException', reason: '* -[NSMutableArray objectAtIndex:]:
index 0 beyond bounds for empty array'
That is I don't store any data in keys. how would I do that? and what would I store?
2: Want the search function to search in my listData array!
Thanks in advance - hope u can help!
You have not finished your sectionIndexTitlesForTableView: method. Right now it is:
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return keys;
There is no closing }, so the compiler thinks everything after that is still part of that method. When you try to define the next method, use use - (NSIndexPath *) to indicate that it is an instance method which returns NSIndexPath*, but the compiler thinks you are trying to subtract something.
The solution is simple: Add the } to the end of sectionIndexTitlesForTableView:.
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return keys;
}