 |
BOOK: Professional iPhone and iPad Database Application Programming
 | This is the forum to discuss the Wrox book Professional iPhone and iPad Database Application Programming by Patrick Alessi; ISBN: 978-0-470-63617-6 |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the BOOK: Professional iPhone and iPad Database Application Programming section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|
|

April 2nd, 2012, 01:38 AM
|
|
Authorized User
|
|
Join Date: Mar 2011
Posts: 16
Thanks: 8
Thanked 0 Times in 0 Posts
|
|
search crashing
Chapter 3 implementing the search, code builds great, loads with no errors and succeeded.
Main screen loads and list is loaded in alphabetical order and can go to next screen view, but when I go to use the search bar the app closes and goes to main screen. I have checked my code against sample and appears to be ok. But I think I may have missed something.
Any pointers where to look. Searching is what I need most to work. :(
If you need my code let me know.
|
|

April 2nd, 2012, 11:01 AM
|
|
Friend of Wrox
|
|
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
|
|
Will need to see code to diagnose.
Send the nonworking project to
[email protected]
and I should be able to sort it out.
Bob
|
|
The Following User Says Thank You to thepianoguy For This Useful Post:
|
|
|

April 4th, 2012, 01:05 AM
|
|
Authorized User
|
|
Join Date: Mar 2011
Posts: 16
Thanks: 8
Thanked 0 Times in 0 Posts
|
|
Working Code
I decided to have one final attempt at this before troubling ThePianoGuy. Started from Scratch, the code worked. No crashing no problems every great.
Checked code against non working project, found a typo used a instead of @, but it still won't work. Copied and pasted new project into old and works like a charm.
Still can't see where I went wrong. If anyone is bored and wants to try
here is non-working code
Code:
#import "RootViewController.h"
@implementation RootViewController
@synthesize croplists;
@synthesize filteredCrops;
@synthesize searchBar;
@synthesize searchController;
- (void)viewDidLoad {
[super viewDidLoad];
self.croplists = [NSMutableArray arrayWithCapacity:1];
NSMutableArray *croplistsTemp;
// get the DBAccess object
DBAccess *dbAccess = [[DBAccess alloc] init];
// get the array from the database
croplistsTemp = [dbAccess getAllCropLists];
// close the database finished with it
[dbAccess closeDatabase];
// release the dbAccess object to free its memory
[dbAccess release];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
UILocalizedIndexedCollation *indexedCollation = [UILocalizedIndexedCollation currentCollation];
// iterate over the crops, populating their section number
for (CropList *theCropList in croplistsTemp) {
NSInteger section = [indexedCollation sectionForObject:theCropList collationStringSelector:@selector(name)];
theCropList.section = section;
}
// get the count of the number of sections
NSInteger sectionCount = [[indexedCollation sectionTitles] count];
// create an array to hold the sub arrays
NSMutableArray *sectionsArray = [NSMutableArray arrayWithCapacity:sectionCount];
// interate over each section, creating each sub array
for (int i=0; i<=sectionCount; i++) {
NSMutableArray *singleSectionArray = [NSMutableArray arrayWithCapacity:1];
[sectionsArray addObject:singleSectionArray];
}
// iterate over the crops putting each crop into the correct sub-array
for (CropList *theCropList in croplistsTemp) {
[(NSMutableArray *) [sectionsArray objectAtIndex:theCropList.section] addObject:theCropList];
}
// iterate over each section array to sort the items in the section
for (NSMutableArray *singleSectionArray in sectionsArray) {
// use the UILocalizedIndexedCollation sortedArrayFromArray: method to sort each array
NSArray *sortedSection = [indexedCollation sortedArrayFromArray:singleSectionArray collationStringSelector:@selector(name)];
[self.croplists addObject:sortedSection];
}
// create search bar
self.searchBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)] autorelease];
self.tableView.tableHeaderView = self.searchBar;
// create and configure the search controller
self.searchController = [[[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self] autorelease];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
}
/*
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
*/
/*
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
*/
/*
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
*/
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return YES; //(interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark Table view methods
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// is the request for numberOfRowsInSection for the regular table?
if (tableView == self.tableView)
{
// return the count of the crops as normal
return [self.croplists count];
}
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// is the request for numberOfRowsInSection for the regular table?
if (tableView == self.tableView)
{
// just return the count of the crops as normal
return [[self.croplists objectAtIndex:section] count];
}
// count for the filtered table
// first, flatten the array of arrays self.croplists
NSMutableArray *flattenedArray = [[NSMutableArray alloc] initWithCapacity:1];
for (NSMutableArray *theArray in self.croplists)
{
for (int i=0; i<[theArray count]; i++)
{
[flattenedArray addObject:[theArray objectAtIndex:i]];
}
}
// setup the NSPredicate to filter the rows
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name begins with[c] %@", self.searchBar.text];
self.filteredCrops = [flattenedArray filteredArrayUsingPredicate:predicate];
// clean up flattened array
[flattenedArray release];
return self.filteredCrops.count;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
CropTableViewCell *cell = (CropTableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CropTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
cell.accessoryType = UITableViewCellAccessoryNone;
// is the request for cellForRowAtIndexPath for the regular path?
if (tableView == self.tableView)
{
// get the crop object
CropList *croplist = [[self.croplists objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
// set the crop to be used to draw the cell
[cell setCropList:croplist];
return cell;
}
// get the crop object
CropList *croplist = [self.filteredCrops objectAtIndex:[indexPath row]];
// set the crop to be used to draw the cell
[cell setCropList:croplist];
return cell;
}
// override to support row selection in the table view
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// get the crop that corresponds with the cell selected
CropList *croplist;
if (tableView == self.tableView)
{
// get the crop that corresponds with the touched cell
croplist = [[self.croplists objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
}
else {
croplist = [self.filteredCrops objectAtIndex:[indexPath row]];
}
//initialise detail view controller from the NIB xib file
CropListDetailViewController *cropListDetailViewController = [[CropListDetailViewController alloc] initWithNibName:@"CropListDetailViewController" bundle:nil];
// set titles of detail page
[cropListDetailViewController setTitle:croplist.name];
// push detail controller to the stack
[self.navigationController pushViewController:cropListDetailViewController animated:YES];
// populate the details
[cropListDetailViewController setLabelsForCropList:croplist];
// release the view controller
[cropListDetailViewController release];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
// make sure that the section will contain some data
if ([[self.croplists objectAtIndex:section] count] >0) {
// if it does, get the section title from the UILocalizedIndexedCollation object
return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:section];
}
return nil;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
if (tableView == self.tableView)
{
// setup the index titles from the UILocaliszedIndexedCollation
return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles];
}
return nil;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex: (NSInteger)index {
// link the sections to the labels in the table
return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}
/*
// 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:[NSArray arrayWithObject: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 -
#pragma mark Memory Management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
@end
and the working code
Code:
#import "RootViewController.h"
@implementation RootViewController
@synthesize croplists;
@synthesize filteredCrops;
@synthesize searchBar;
@synthesize searchController;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.croplists = [NSMutableArray arrayWithCapacity:1];
NSMutableArray *croplistsTemp;
// get the DBAccess object
DBAccess *dbAccess = [[DBAccess alloc] init];
// get the array from the database
croplistsTemp = [dbAccess getAllCropLists];
// close the database finished with it
[dbAccess closeDatabase];
// release the dbAccess object to free its memory
[dbAccess release];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
UILocalizedIndexedCollation *indexedCollation = [UILocalizedIndexedCollation currentCollation];
// iterate over the crops, populating their section number
for (CropList *theCropList in croplistsTemp) {
NSInteger section = [indexedCollation sectionForObject:theCropList collationStringSelector:@selector(name)];
theCropList.section = section;
}
// get the count of the number of sections
NSInteger sectionCount = [[indexedCollation sectionTitles] count];
// create an array to hold the sub arrays
NSMutableArray *sectionsArray = [NSMutableArray arrayWithCapacity:sectionCount];
// interate over each section, creating each sub array
for (int i=0; i<=sectionCount; i++) {
NSMutableArray *singleSectionArray = [NSMutableArray arrayWithCapacity:1];
[sectionsArray addObject:singleSectionArray];
}
// iterate over the crops putting each crop into the correct sub-array
for (CropList *theCropList in croplistsTemp) {
[(NSMutableArray *) [sectionsArray objectAtIndex:theCropList.section] addObject:theCropList];
}
// iterate over each section array to sort the items in the section
for (NSMutableArray *singleSectionArray in sectionsArray) {
// use the UILocalizedIndexedCollation sortedArrayFromArray: method to sort each array
NSArray *sortedSection = [indexedCollation sortedArrayFromArray:singleSectionArray collationStringSelector:@selector(name)];
[self.croplists addObject:sortedSection];
}
// create searchBar
self.searchBar = [[[UISearchBar alloc] initWithFrame: CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)] autorelease];
self.tableView.tableHeaderView = self.searchBar;
// create search Controller
self.searchController = [[[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self] autorelease];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
}
/*
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
*/
/*
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
*/
/*
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
#pragma mark Table view methods
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// is the request for numberOfRowsInSection for the regular table
if (tableView == self.tableView)
{
// just return the count of the crops like before
return [self.croplists count];
}
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// is the request for numberOfRowsInSection for the regular table
if (tableView == self.tableView)
{
// just return the count of the crops like before
return [[self.croplists objectAtIndex:section] count];
}
// count for the filtered table
// first, flatten the array of arrays self.crops
NSMutableArray *flattenedArray = [[NSMutableArray alloc] initWithCapacity:1];
for (NSMutableArray *theArray in self.croplists)
{
for (int i=0; i<[theArray count]; i++)
{
[flattenedArray addObject:[theArray objectAtIndex:i]];
}
}
// setup an NSPredicate to filter the rows
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name beginswith[c]%@", self.searchBar.text];
self.filteredCrops = [flattenedArray filteredArrayUsingPredicate:predicate];
//clean up the array
[flattenedArray release];
return self.filteredCrops.count;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
CropTableViewCell *cell = (CropTableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CropTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
cell.accessoryType = UITableViewCellAccessoryNone;
// is the request for cellForRowAtIndexPath for the regular table?
if (tableView == self.tableView)
{
// get the crop object
CropList *croplist = [[self.croplists objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
// set the crop to be used to draw the cell
[cell setCropList:croplist];
return cell;
}
// get the crop object
CropList* croplist = [self.filteredCrops objectAtIndex:[indexPath row]];
// set the crop to be used to draw the cell
[cell setCropList:croplist];
return cell;
}
/*
// 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:[NSArray arrayWithObject: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 -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// get the crop that corresponds with the cell selected
CropList *croplist;
if (tableView == self.tableView)
{
//get the crop that corresponds iwth the touched cell
croplist = [[self.croplists objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
}
else {
croplist = [self.filteredCrops objectAtIndex:[indexPath row]];
}
//initialise detail view controller from the NIB xib file
CropListDetailViewController *cropListDetailViewController = [[CropListDetailViewController alloc] initWithNibName:@"CropListDetailViewController" bundle:nil];
// set titles of detail page
[cropListDetailViewController setTitle:croplist.name];
// push detail controller to the stack
[self.navigationController pushViewController:cropListDetailViewController animated:YES];
// populate the details
[cropListDetailViewController setLabelsForCropList:croplist];
// release the view controller
[cropListDetailViewController release];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
// make sure that the section will contain some data
if ([[self.croplists objectAtIndex:section] count] >0) {
// if it does, get the section title from the UILocalizedIndexedCollation object
return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:section];
}
return nil;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
if (tableView == self.tableView)
{
// setup the index titles from the UILocaliszedIndexedCollation
return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles];
}
return nil;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex: (NSInteger)index {
// link the sections to the labels in the table
return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
@end
Thanks Bob for the offer of testing code.
|
|

April 4th, 2012, 08:08 AM
|
|
Friend of Wrox
|
|
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
|
|
Your difference is how you created your NSPredicate in the
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
method
the incorrect predicate is
Code:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name begins with[c] %@", self.searchBar.text];
and the correct one is
Code:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name beginswith[c] %@", self.searchBar.text];
There should not be a space between "begins" and "with".
Bob
|
|
The Following User Says Thank You to thepianoguy For This Useful Post:
|
|
|

April 4th, 2012, 08:15 PM
|
|
Authorized User
|
|
Join Date: Mar 2011
Posts: 16
Thanks: 8
Thanked 0 Times in 0 Posts
|
|
Thanks
that was it. I feel should a fool. Something so simple, but I just couldn't see it.
thanks, you are awesome.
|
|

April 4th, 2012, 11:21 PM
|
|
Friend of Wrox
|
|
Join Date: Aug 2010
Posts: 298
Thanks: 1
Thanked 62 Times in 60 Posts
|
|
The console log in the debugger actually gives a very strong indication as to where the problem was.
This is part of the log I got when I ran your code:
2012-04-04 22:59:38.141 Catalog[1005:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "name begins with[c] %@"'
*** First throw call stack:etc
Glad you got it working.
Bob
|
|
The Following User Says Thank You to thepianoguy For This Useful Post:
|
|
|

April 5th, 2012, 12:15 AM
|
|
Authorized User
|
|
Join Date: Mar 2011
Posts: 16
Thanks: 8
Thanked 0 Times in 0 Posts
|
|
thank you again. I had used the debugger but not the debugger console, how that I know how to use that, I can find things myself. But have this forum as backup.
Just when I think I am getting confident with Xcode I learn something new. But it is fun.
|
|
 |
|