UISearchBar and UIImageView with a plist

Discussion in 'iOS Programming' started by n00bz0rd2, Apr 1, 2010.

  1. n00bz0rd2 macrumors member

    Joined:
    Mar 26, 2010
    #1
    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!
     
  2. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #2
    Without any code and crash log info for us to look at, there's very little we can do to help.
     
  3. n00bz0rd2 thread starter macrumors member

    Joined:
    Mar 26, 2010
    #3
    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.
     
  4. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #4
    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.
     
  5. n00bz0rd2 thread starter macrumors member

    Joined:
    Mar 26, 2010
    #5
    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.
     
  6. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #6
    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.

    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.
     
  7. n00bz0rd2 thread starter macrumors member

    Joined:
    Mar 26, 2010
    #7
    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.
     
  8. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #8
    Or, it may be that you have not set up your DataPath correctly, and thus, the code is not able to retrieve the file.

    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?
     
  9. n00bz0rd2 thread starter macrumors member

    Joined:
    Mar 26, 2010
    #9
    DataPath is being used for my drill down menus so it is setup correctly.

    My plist is attached.
     

    Attached Files:

  10. n00bz0rd2 thread starter macrumors member

    Joined:
    Mar 26, 2010
    #10
    Just to update, I have managed to get my images working. The search is the only thing left for me to do!
     
  11. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #11
    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.
     
  12. n00bz0rd2 thread starter macrumors member

    Joined:
    Mar 26, 2010
    #12
    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?
     
  13. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #13
    Rebuild your plist so that you've eliminated the Dictionary Root and have a Array in its place.
     
  14. n00bz0rd2 thread starter macrumors member

    Joined:
    Mar 26, 2010
    #14
    But by doing that my drill downs will not work
     
  15. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #15
    Then you probably need to redo the code for them as well. Having a Dictionary as Root that only contains one item, an Array, seems superfluous to me.
     
  16. bradnet macrumors newbie

    Joined:
    Mar 8, 2010
    #16
    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
     

Share This Page