Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

n00bz0rd2

macrumors member
Original poster
Mar 26, 2010
41
3
I have a plist with info. It is setup like this:

Code:
> Root (dictionary)
   > Rows (array)
      > Item 1 (dictionary)
         > Children (array)
            > Item 1 (dictionary)
               > Title (string)
               > Time (string)
               > etc.
            > Item 2 (dictionary)
               > Title (string)
               > Time (string)
               > etc.
      > Item 2 (dictionary)
         > Children (array)
            > Item 1 (dictionary)
               > Title (string)
               > Time (string)
               > etc.
            > Item 2 (dictionary)
               > Title (string)

Under each array, there are more items. How can I implement a search bar that searches through all of the Titles? I have used the tutorial in the Beginning iPhone Development book, but when I want to use my own plist is crashes (due the way my plist is).

Secondly, I want to hold some image paths in my plist and get them to display on my detailview. How can I do that? - I've managed to get this working using this tutorial http://www.iphonesdkarticles.com/2009/03/drill-down-table-view-with-detail-view.html

Thanks in advanced!
 
Sorry about that. Since posting, I've tried to use Apple's TableSearch example. It will build but nothing appears in the table and the search still doesn't work.

Delegate.h
Code:
#import <UIKit/UIKit.h>

@class SearchViewController;

@interface TS_RecipesAppDelegate : NSObject <UIApplicationDelegate> {
    
    UIWindow *window;
	UITabBarController *tabcontroller;
    UINavigationController *navigationController;	
	UIImageView *splashView;	
	NSDictionary *data;
	SearchViewController *viewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabcontroller;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@property (nonatomic, retain) NSDictionary *data;
@property (nonatomic, retain) SearchViewController *viewController;

@end

Delegate.m
Code:
#import "TS_RecipesAppDelegate.h"
#import "RootViewController.h"
#import "SearchViewController.h"


@implementation TS_RecipesAppDelegate

@synthesize window, navigationController, tabcontroller, data, viewController;


- (void)applicationDidFinishLaunching:(UIApplication *)application {
	
	NSString *Path = [[NSBundle mainBundle] bundlePath];
	NSString *DataPath = [Path stringByAppendingPathComponent:@"Data.plist"];
	
	NSArray *listContent = [NSArray arrayWithContentsOfFile:DataPath];
	
	SearchViewController *searchViewController = [[SearchViewController alloc] initWithNibName:@"SearchViewController" bundle:nil];
	searchViewController.listContent = listContent;
	[listContent release];
	
	UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:searchViewController];
	self.navigationController = navController;
	[navController release];
	
	NSDictionary *tempDict = [[NSDictionary alloc] initWithContentsOfFile:DataPath];
	self.data = tempDict;
	[tempDict release];
	[window addSubview:viewController.view];
	[window addSubview:tabcontroller.view];
	[window makeKeyAndVisible];
	
	splashView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
	splashView.image = [UIImage imageNamed:@"Default1.png"];	
	
	// Configure and show the window
	[window addSubview:splashView];
	[window bringSubviewToFront:splashView];
	[UIView beginAnimations:nil context:nil];
	[UIView setAnimationDuration:2.5];
	[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:window cache:YES];
	[UIView setAnimationDelegate:self]; 
	[UIView setAnimationDidStopSelector:@selector(startupAnimationDone:finished:context:)];
	splashView.alpha = 0.0;
	[UIView commitAnimations];
}

- (void)startupAnimationDone:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
	[splashView removeFromSuperview];
	[splashView release];
}

- (void)applicationWillTerminate:(UIApplication *)application {
	// Save data if appropriate
}


- (void)dealloc {
	[viewController release];
	[data release];
	[navigationController release];
	[tabcontroller release];
	[window release];
	[super dealloc];
}

@end

SearchViewController.h
Code:
#import <UIKit/UIKit.h>

@interface SearchViewController : UITableViewController <UISearchBarDelegate, UISearchDisplayDelegate>
{
	NSArray *listContent;
    NSMutableArray  *filteredListContent;
	
	NSString *savedSearchTerm;
	NSInteger savedScopeButtonIndex;
		
	BOOL searchWasActive;
}

@property (nonatomic, retain) NSArray *listContent;
@property (nonatomic, retain) NSMutableArray *filteredListContent;

@property (nonatomic, copy) NSString *savedSearchTerm;
@property (nonatomic) NSInteger savedScopeButtonIndex;
@property (nonatomic) BOOL searchWasActive;

@end

SearchViewController.m
Code:
#import "SearchViewController.h"
#import "DetailViewController.h"

@implementation SearchViewController

@synthesize listContent, filteredListContent, savedSearchTerm, savedScopeButtonIndex, searchWasActive;

- (void)viewDidLoad {
	
	self.title = @"Search";
	
	self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.listContent count]];
	
	if (self.savedSearchTerm)
	{
		[self.searchDisplayController setActive:self.searchWasActive];
		[self.searchDisplayController.searchBar setText:savedSearchTerm];
		
		self.savedSearchTerm = nil;
	}
	
	[self.tableView reloadData];
	self.tableView.scrollEnabled = YES;
}


- (void)viewDidUnload
{
	self.filteredListContent = nil;
}

- (void)viewDidDisappear:(BOOL)animated
{
    // save the state of the search UI so that it can be restored if the view is re-created
    self.searchWasActive = [self.searchDisplayController isActive];
    self.savedSearchTerm = [self.searchDisplayController.searchBar text];
    self.savedScopeButtonIndex = [self.searchDisplayController.searchBar selectedScopeButtonIndex];
}

- (void)dealloc
{
	[listContent release];
	[filteredListContent release];
	
	[super dealloc];
}


#pragma mark -
#pragma mark UITableView data source and delegate methods

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
	/*
	 If the requesting table view is the search display controller's table view, return the count of
     the filtered list, otherwise return the count of the main list.
	 */
	if (tableView == self.searchDisplayController.searchResultsTableView)
	{
        return [self.filteredListContent count];
    }
	else
	{
        return [self.listContent count];
    }
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	static NSString *kCellID = @"cellID";
	
	UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
	if (cell == nil)
	{
		cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellID] autorelease];
		cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
	}
	
	/*
	 If the requesting table view is the search display controller's table view, configure the cell using the filtered content, otherwise use the main list.
	 */
	
	return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIViewController *DetailViewController = [[UIViewController alloc] init];
    
	/*
	 If the requesting table view is the search display controller's table view, configure the next view controller using the filtered content, otherwise use the main list.
	 */
    [[self navigationController] pushViewController:DetailViewController animated:YES];
    [DetailViewController release];
}


#pragma mark -
#pragma mark Content Filtering

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
	/*
	 Update the filtered array based on the search text and scope.
	 */
	
	[self.filteredListContent removeAllObjects]; // First clear the filtered array.
	
	/*
	 Search the main list for products whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array.
	 */
	}


#pragma mark -
#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 to cause the search result table view to be reloaded.
    return YES;
}


- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
	 [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
    
    // Return YES to cause the search result table view to be reloaded.
    return YES;
}


@end

That is all of the relevant code. I feel it is something fairly simple but I cannot figure it out.
 
Two things.

1) Time to do some debugging. What is the size (count) of listContent after the following line in applicationDidFinishLaunching: has executed?
Code:
NSArray *listContent = [NSArray arrayWithContentsOfFile:DataPath];

2) filterContentForSearchText:scope: doesn't actually do any filtering. It just wipes out filteredListContent.
 
1. In my log: "Size of loaded array 0". I am guessing thats why nothing is working. How can I fill up the array?

2. The reason the scopes are in there is because the Apple source code included it. I don't need it in my app.
 
1. In my log: "Size of loaded array 0". I am guessing thats why nothing is working. How can I fill up the array?
I would suspect that either arrayWithContentsOfFile: is unable to find a file at that path or the contents of that file are not able to be parsed into an array.

2. The reason the scopes are in there is because the Apple source code included it. I don't need it in my app.
I'm not worried about the scopes. I'm worried that the only method that seems to be responsible for actually filtering the content, doesn't do so at all; it just removes all the objects from the filtered list and returns.
 
The file is definitely in my application bundle. So I presume it is not being parsed properly. Is the hierarchy of the plist the reason why I can't fill the array? If so, how can I do it?

[Edit] I tried putting the contents of the plist into a dictionary and then using the dictionary to fill the plst. Same result. Nothing appears.
 
The file is definitely in my application bundle. So I presume it is not being parsed properly.
Or, it may be that you have not set up your DataPath correctly, and thus, the code is not able to retrieve the file.

Is the hierarchy of the plist the reason why I can't fill the array? If so, how can I do it?
Without knowing exactly what is in your Data.plist file, we can't say either way. Can you attach it to a post in this thread?
 
Or, it may be that you have not set up your DataPath correctly, and thus, the code is not able to retrieve the file.
DataPath is being used for my drill down menus so it is setup correctly.

Without knowing exactly what is in your Data.plist file, we can't say either way. Can you attach it to a post in this thread?

My plist is attached.
 

Attachments

  • Data.plist.zip
    4.9 KB · Views: 166
Just to update, I have managed to get my images working. The search is the only thing left for me to do!
 
I'm thinking the problem might be that your plist has a Dictionary at the Root, whereas arrayWithContentsOfFile: expects the Root to be an Array. All examples that I've seen that use arrayWithContentsOfFile:, have an Array as Root.
 
I'm thinking the problem might be that your plist has a Dictionary at the Root, whereas arrayWithContentsOfFile: expects the Root to be an Array. All examples that I've seen that use arrayWithContentsOfFile:, have an Array as Root.

So what would be a way around this? Obviously I can't simply change the Root from a dictionary to an array, so what would I need to do to get it working?
 
UISearchBar Solution

Hi n00bz0rd2

Did you ever manage to get your search method working without the scope setting as i'm having the same problem myself at the minute, i am using the code supplied by apple but i'm unsure which section to remove for the scope.

I have a plist the same as yourself loaded into an array which populates the tableview, i need to search this array and return the key called text from the array.

Thanks
Brad
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.