Adding a Search Bar to a Table View Run and Crash - ios

hi everyone
i am using the code in below without using storyboard and its run ok, but its crash when i write the second letter of searching word.
anyone can help me
in ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) IBOutlet UITableView *tableView;
#property (retain, nonatomic) IBOutlet UILabel *nameLabel;
#end
in ViewController.m
#import "ViewController.h"
#import "DetailController.h"
#interface ViewController ()
#end
#implementation ViewController {
NSArray *peopleName;
NSArray *searchResult;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
peopleName = [[NSArray alloc] initWithObjects:#"john", #"Waseem", #"Bruce", #"Ammar", #"Londol", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[_nameLabel release];
[super dealloc];
}
//
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResult count];
} else {
return [peopleName count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResult objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [peopleName objectAtIndex:indexPath.row];
}
return cell;
}
#pragma mark - UISearchDisplayController delegate methods
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResult = [peopleName filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
#end
its crash and show me this
cell.textLabel.text = [searchResult objectAtIndex:indexPath.row];
(lldb)
Thread 1:EXC_BAD_ACCESS (code=2, address=0x8)

Used the below code snippet:
#pragma mark - UISearchDisplayController delegate methods
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
[searchResult release];
searchResult = [peopleName filteredArrayUsingPredicate:resultPredicate]retain];
}

Related

My SearchDisplayController doesn't work well with UITableView in UIViewController

Here I have a Search Bar on the top of the UIViewController, and also a UITableView below the Search Bar.
When I don't Search things, the tableView could display things well, but when I search, the searchResultTableView can only show some white cell, not the correct result.
Here is the .h file:
#import <UIKit/UIKit.h>
#interface MySearchViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UITableView *myTableView;
- (void)reloadView;
#end
And here is the .m file:
#import "MySearchViewController.h"
#import "MyEventInfo.h"
#import "MyEventTableViewCell.h"
#import "MyEventDetailViewController.h"
#interface MySearchViewController ()
#property NSUserDefaults *usrDefault;
#end
#implementation MySearchViewController {
NSMutableArray *events;
NSArray *searchResults;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.usrDefault = [NSUserDefaults standardUserDefaults];
events = [[NSMutableArray alloc] init];
[self extractEventArrayData];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
[self reloadView];
}
- (void)reloadView {
NSLog(#"reloadView");
events = [[NSMutableArray alloc] init];
[self extractEventArrayData];
[self.myTableView reloadData];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)extractEventArrayData {
NSArray *dataArray = [[NSArray alloc] initWithArray:[self.usrDefault objectForKey:#"eventDataArray"]];
for (NSData *dataObject in dataArray) {
MyEventInfo *eventDecodedObject = [NSKeyedUnarchiver unarchiveObjectWithData:dataObject];
[events addObject:eventDecodedObject];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.myTableView) {
return [events count];
} else {
NSLog(#"searchResults count:%lu",(unsigned long)[searchResults count]);
return [searchResults count];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 360;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomTableCell";
MyEventTableViewCell *cell = (MyEventTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil) {
cell = [[MyEventTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Display MyEventTableViewCell in the table cell
MyEventInfo *event = nil;
if (tableView == self.myTableView) {
event = [events objectAtIndex:indexPath.row];
} else {
event = [searchResults objectAtIndex:indexPath.row];
NSLog(#"name of event:%#", event.nameOfEvent);
}
cell.nameOfEvent.text = event.nameOfEvent;
cell.imageOfEvent.image = [UIImage imageNamed:event.imageOfEvent];
cell.timeOfEvent.text = event.timeOfEvent;
cell.locationOfEvent.text = event.locationOfEvent;
cell.dateOfEvent.text = event.dateOfEvent;
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"nameOfEvent contains[c] %#", searchText];
searchResults = [events filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString];
return YES;
}
#end
And on the storyboard I've already set the tableView's delegate and datasource to self. This drives me crazy, I cannot figure out what's wrong. Could someone help me out? Thanks.
when searching, cell's objects were all null, and had nothing in itself
when not searching, the cell is well with objects that had content the same as event

search bar not working and cant select row from table

I cant select row from table data and also cant access search bar via search bar display.When i run this it don't select any row, only dismiss tableview ..i connect search bar with file owner.Below i am showing all methods Could any one help me??
#protocol CityListDelegate<NSObject>
-(void)returnCityName:(NSString*)cityName;
#end
#interface CityViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
{
int index;
//NSArray *cityList;
}
#property (weak, nonatomic) IBOutlet UITableView *cityTableView;
#property(nonatomic, retain)id<CityListDelegate> delegate;
#property (nonatomic, strong) NSMutableArray *SearchCityResult;
#property (nonatomic, strong) NSMutableArray *CityList;
/////.m file
#synthesize CityList;
#pragma mark Table view methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.SearchCityResult count];
}
else
{
return [self.CityList count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView==self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.SearchCityResult objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = self.CityList [indexPath.row];
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)IndexPath
{
if (tableView==self.searchDisplayController.searchResultsTableView)
{
[self.delegate returnCityName:[self.SearchCityResult objectAtIndex:IndexPath.row]];
}
else
{
[self.delegate returnCityName:[CityList objectAtIndex:IndexPath.row]];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.SearchCityResult removeAllObjects];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchText];
self.SearchCityResult = [NSMutableArray arrayWithArray: [self.CityList filteredArrayUsingPredicate:resultPredicate]];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
Be more precise about the setup, did you use the storyboard?
And make sure you use the right delegate methods. Looks like you named the indexPath paramter of didSelectRowAtIndexPath wrong, should be indexPath.

Implementing PFQueryTableViewController search function

I need help setting up a PFQTVC search function. I have most of it complete but am stuck on how to switch the local data (self.tabledata) for the remote data (self.objects). Here is my code. Im stuck on the filterContentForSearchText method.
#import "ViewController.h"
#interface ViewController () <UISearchDisplayDelegate>
#property (nonatomic, strong) NSArray *tableData;
#property (nonatomic, strong) NSMutableArray *searchResult;
#end
#implementation ViewController
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// Custom the table
// The className to query on
self.parseClassName = #"profs";
// 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 = YES;
// The number of objects to show per page
self.objectsPerPage = 500;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// self.tableData = #[#"One",#"Two",#"Three",#"Twenty-one"];
self.searchResult = [NSMutableArray arrayWithCapacity:[self.objects count]];
}
- (PFQuery *)queryForTable
{
PFQuery *query;
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;
}*/
return query;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView)
{
return [self.searchResult count];
}
else
{
return [self.objects count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.searchResult objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = [object objectForKey:#"name"];
}
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.searchResult removeAllObjects];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchText];
self.searchResult = [NSMutableArray arrayWithArray: [self.tableData filteredArrayUsingPredicate:resultPredicate]];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
#end
Try this:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.searchResult removeAllObjects];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"%K CONTAINS[c] %#", YOUR_FIELD_TO_COMPARE, searchText];
self.searchResult = [NSMutableArray arrayWithArray: [self.tableData filteredArrayUsingPredicate:resultPredicate]];
}
YOUR_FIELD_TO_COMPARE is the field name for the value you are comparing in the search, e.g. "name"

UISearchBar issues Xcode 5

I am having issues with my UISearchBar that I have implemented. My app will compile and run, but as soon as I hit the search bar to begin typing a word in, it crashes. Can anyone tell me if you see anything wrong with my syntax? It is suppose to go through the states that I have in my NSArray.
TableViewController.h:
#import <UIKit/UIKit.h>
#interface TableViewController : UITableViewController <UISearchBarDelegate>
#property (nonatomic, strong) NSMutableArray *results;
#property (nonatomic, strong) IBOutlet UISearchBar *searchBar;
#end
TableViewController.m:
#import "TableViewController.h"
#import "ViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
{
NSArray *states;
}
- (NSMutableArray *)results
{
if (!_results)
{
_results = [[NSMutableArray alloc] init];
}
return _results;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
states = [NSArray arrayWithObjects:#"Alabama", #"Georgia", #"Tennessee", #"Colorado", nil];
}
- (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 = [[states 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 [states 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 = [states objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = self.results[indexPath.row];
}
return cell;
}
I am fairly new to Objective-C, so sorry if this is a simple question that I should know the answer to.
Thanks
The first line of your - (void)searchThroughData method sets the NSMutableArray to nil. This may be the problem.

adding search to NSMutable Array with DetailView

i have project that I'm working on and i need to add search to my uitableview. i have been looking at lots of codes but mostly they are not what i am looking for and i can't modify them . can someone please help me with adding search to my tableview. also i want to push the detailview from searcharray. thank you in advance.
here is the .h uitableview
#import <UIKit/UIKit.h>
#interface Reds : UITableViewController {
NSMutableArray *dummyArray;
}
- (void) setupData;
#end
here is .m uitableview
#import "Reds.h"
#import "RedsDetail.h"
#interface Reds ()
#end
#implementation Reds
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupData];
}
- (void) setupData {
dummyArray = [[NSMutableArray alloc] init];
[dummyArray addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:#"dummy 1", #"name" , #"image1.JPG", #"image" , #"dummy 1 description textview", #"description", nil]];
[dummyArray addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:#"dummy 2", #"name" , #"image1.JPG", #"image" , #"dummy 2 description textview", #"description", nil]];
[dummyArray addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:#"dummy 3", #"name" , #"image1.JPG", #"image" , #"dummy 3 description textview", #"description", nil]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [dummyArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [[dummyArray objectAtIndex:indexPath.row] objectForKey:#"name"];
return cell;
}
#pragma mark - Table view delegate
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"DummyDetail"]){
RedsDetail *dummyDetail = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
dummyDetail.dummyImageString = [[NSString alloc] initWithString:[[dummyArray objectAtIndex:indexPath.row] objectForKey:#"image"]];
dummyDetail.dummyTextString = [[NSString alloc] initWithString:[[dummyArray objectAtIndex:indexPath.row] objectForKey:#"description"]];
dummyDetail.title = [[NSString alloc] initWithString:[[dummyArray objectAtIndex:indexPath.row] objectForKey:#"name"]];
}
}
#end
here is the .h detailview
#import <UIKit/UIKit.h>
#interface RedsDetail : UIViewController {
IBOutlet UIImageView *dummyImage;
IBOutlet UITextView *dummyText;
NSString *dummyImageString;
NSString *dummyTextString;
}
#property (nonatomic, retain) NSString *dummyImageString;
#property (nonatomic, retain) NSString *dummyTextString;
#end
and finally the .m detailview
#import "RedsDetail.h"
#interface RedsDetail ()
#end
#implementation RedsDetail
#synthesize dummyImageString, dummyTextString;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
dummyImage.image = [UIImage imageNamed:dummyImageString];
dummyText.text = dummyTextString;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
i know it might be a easy answer for most of you guys out there but i can't figure it out and i need help. i truly appreciate the time you guys spending in helping me. also i am using xcode 4.5 ios 6 storyboard if that makes a difference in your answers.
adrian
For the search, create a searchArray and a searchText, also you need a textfield that invokes the didChange method.
Use this to link the textfield to the didChange method:
[self.searchTextField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
Then in the didChange update the searchText and call the updateSearchArray.
-(void)textFieldDidChange:(UITextField*)textField
{
searchTextString = textField.text;
[self updateSearchArray];
}
In the updateSearchArray you compare go through the original array (dummyArray) and if the name is included in the search then add it to the searchArray.
-(void)updateSearchArray
{
if (searchTextString.length != 0) {
searchArray = [NSMutableArray array];
for ( NSDictionary* item in dummyArray ) {
if ([[[item objectForKey:#"name"] lowercaseString] rangeOfString:[searchTextString lowercaseString]].location != NSNotFound) {
[searchArray addObject:item];
}
}
} else {
searchArray = dummyArray;
}
[self.tableView reloadData];
}
Use the searchArray in the tableview methods where you now use the dummyArray.
Updated tableview methods
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [searchArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [[searchArray objectAtIndex:indexPath.row] objectForKey:#"name"];
return cell;
}
Also, you need to call a reloadData after adding all the data to the array. And added the updateSearchArray method
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupData];
[self updateSearchArray];
[self.tableView reloadData];
}
To make it easier to implement this I have made a sample project. You can download it here: http://www.rolandkeesom.com/SearchExample.zip

Resources