edit: I think the problem is in the last referenced code, because when I try to load the table data instead of the search results (by just swapping the arrays) I still get no search results, but I'm still not sure why... Original post in full:
I'm trying to get a search bar working with my table view. I can enter text in the search bar but always find no results. Here's my .h
#interface SecondViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UISearchDisplayDelegate> {
IBOutlet UISearchBar *searchBar;
NSMutableArray *dummyArray;
NSMutableArray *searchArray;
}
#property (nonatomic, strong) NSMutableArray *dummyArray;
#property (nonatomic, strong) NSMutableArray *searchArray;
#property (nonatomic, strong) NSMutableArray *detailArray;
#property (nonatomic, strong) NSMutableArray *imageArray;
- (void) setupArray;
- (void) setupSearchArray;
- (void) setupDetailArray;
#end
In my .m, dummyArray is the array that fills the main cell.textLabel.text and the array i want to search.
I set up searchArray here:
- (void) setupSearchArray{
searchArray = [NSMutableArray arrayWithCapacity:[dummyArray count]];
}
then attempt to make searchArray a filtered version of dummyArray here:
- (BOOL) searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[searchArray removeAllObjects] ;
for (NSString *savedSeachTerm in dummyArray) {
NSRange result = [savedSeachTerm rangeOfString:searchString options:
NSCaseInsensitiveSearch];
if (result.location != NSNotFound)
[searchArray addObject:savedSeachTerm];
}
return YES;
}
and try to populate the table with search results when search text is entered here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchArray objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [detailArray objectAtIndex:indexPath.row];
}
else {
cell.textLabel.text = [dummyArray objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [detailArray objectAtIndex:indexPath.row];
}
if (indexPath.row == 0) {
cell.imageView.image = [UIImage imageNamed:#"row0.png"];
}
return cell;
}
What have I done wrong? Thanks for looking!
I had forgotten to
[self setupSearchArray];
sorry!
Related
I am very new to Objective.I am trying to make a simple application and after adding more view I get this error "Thread 1 Signal SIGABRT" and the app wont open in iOS Simulator. The error points to this line of code:
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
I tried searching before but I didn't understand what the other answers were talking about.
NamesTableViewController.h is :
#import <UIKit/UIKit.h>
#interface NamesTableViewController : UITableViewController <UISearchDisplayDelegate, UISearchBarDelegate>
#property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
#end
NamesTableViewController.m is:
#import "NamesTableViewController.h"
#interface NamesTableViewController ()
#property (nonatomic, copy) NSDictionary *propertyList;
#property (nonatomic, copy) NSArray *letters;
#property (nonatomic, copy)NSMutableArray *filteredNames;
#property (nonatomic, strong)UISearchController *searchController;
#end
#implementation NamesTableViewController
#synthesize propertyList, letters, filteredNames, searchController;
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tableView = (id)[self.view viewWithTag:1];
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
filteredNames = [[NSMutableArray alloc]init];
searchController = [[UISearchController alloc]init];
self.searchController.searchResultsUpdater = self;
NSString *path = [[NSBundle mainBundle] pathForResource:#"names" ofType:#"plist"];
self.propertyList = [NSDictionary dictionaryWithContentsOfFile:path];
self.letters = [[self.propertyList allKeys] sortedArrayUsingSelector:#selector(compare:)];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView.tag == 1){
return self.letters.count;
}else {
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView.tag == 1) {
NSString *letter = self.letters[section];
NSArray *keyValues = [self.propertyList[letter] allKeys];
return keyValues.count;
} else {
return [filteredNames count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
if (tableView.tag == 1){
NSString *letter = self.letters[indexPath.section];;
NSArray *keyValues = [[self.propertyList[letter] allKeys] sortedArrayUsingSelector:#selector(compare:)];
cell.textLabel.text = keyValues[indexPath.row];
} else{
cell.textLabel.text = filteredNames[indexPath.row];
}
return cell;
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.letters;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (tableView.tag == 1) {
return letters [section];
} else {
return nil;
}
}
#pragma mark Search Display Delegate Methods
-(void)searchDisplayController:(UISearchController *)controller didLoadSearchResultsTableView:(UITableView *)tableView {
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
}
-(BOOL)searchDisplayController:(UISearchController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[filteredNames removeAllObjects];
if (searchString.length > 0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains [search] %#", self.searchBar.text];
for (NSString *letter in letters) {
NSArray *matches = [[self.propertyList[letter] allKeys]filteredArrayUsingPredicate:predicate];
[filteredNames addObjectsFromArray:matches];
}
}
return YES;
}
#end
If you want more information just say it to me by answers and I will edit my question and then you will edit your answer
[keys allKeys] returns an single-level array. Therefore there can be only one section.
Edit:
For better understanding and readability I replaced names with letters and keys with propertyList
• .h
The methods numberOfRowsInSection and cellForRowAtIndexPath retrieve the section letter and then the appropriate keys from the property list.
A dictionary as data source is not the best choice because there are many repetitive tasks to perform for example the sorting. Better create an nested array as data source in viewDidLoad
#interface NamesTableViewController ()
#property (nonatomic, copy) NSDictionary *propertyList;
#property (nonatomic, copy) NSArray *letters;
#end
• .m
#implementation NamesTableViewController
#synthesize propertyList, letters;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"names" ofType:#"plist"];
self.propertyList = [NSDictionary dictionaryWithContentsOfFile:path];
self.letters = [[self.propertyList allKeys] sortedArrayUsingSelector:#selector(compare:)];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.letters.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *letter = self.letters[section];
NSArray *keyValues = [self.propertyList[letter] allKeys];
return keyValues.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSString *letter = self.letters[indexPath.section];
NSArray *keyValues = [[self.propertyList[letter] allKeys] sortedArrayUsingSelector:#selector(compare:)];
cell.textLabel.text = keyValues[indexPath.row];
return cell;
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.letters;
}
#end
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.
I'm new to the whole iOS developement, so not really good at it. I currently have a viewController with two tableviews. The first table is always visible and contains categories. The second table should only be visible when a cell from the first table is selected. The second table then contains subitems from the cell that was selected in the first tableview. Both tableviews are connected to their property in the .h file.
The viewcontroller itself is connected to a FoodAddViewController.h and FoodAddViewController.m file.
In the FoodAddViewController.h file, I have:
#import <UIKit/UIKit.h>
#class FoodAddViewController;
#interface FoodAddViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UITableView *Categorien;
#property (strong, nonatomic) IBOutlet UITableView *Invulling;
- (IBAction)cancel:(id)sender;
#end
For the FoodAddViewController.m, I have:
#interface FoodAddViewController ()
{
NSArray *CategoryLabel;
NSMutableArray *elementen;
}
#end
#implementation FoodAddViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.Categorien.layer.transform = CATransform3DRotate(CATransform3DIdentity,-1.57079633,0,0,1);
self.Categorien.frame=CGRectMake(0,200, 700,234);
[self.Invulling setHidden:TRUE];
self.Invulling.layer.transform = CATransform3DRotate(CATransform3DIdentity,-1.57079633,0,0,1);
self.Invulling.frame=CGRectMake(0,200, 700,234);
self.Categorien.dataSource = self;
self.Categorien.delegate = self;
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"categorie" ofType:#"txt"];
NSString *content = [NSString stringWithContentsOfFile:filePath
encoding:NSMacOSRomanStringEncoding
error:NULL];
NSArray * categories = [content componentsSeparatedByString:#"\n"];
CategoryLabel = categories;
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(self.Categorien==tableView) {
return CategoryLabel.count;
}
if(self.Invulling==tableView) {
return elementen.count;
}
return 0;
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(self.Categorien==tableView) {
static NSString *CellIdentifier = #"Cell";
CustomCell *Cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!Cell) {
Cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Cell.layer.transform = CATransform3DRotate(CATransform3DIdentity,1.57079633,0,0,1);
Cell.frame=CGRectMake(0,0,234,150);
Cell.textLabel.text = [CategoryLabel objectAtIndex:indexPath.row];
return Cell;
}
if(self.Invulling==tableView) {
static NSString *CellIdentifier = #"DetailCell";
CustomCell *Cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!Cell) {
Cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Cell.layer.transform = CATransform3DRotate(CATransform3DIdentity,1.57079633,0,0,1);
Cell.frame=CGRectMake(0,0,234,150);
Cell.textLabel.text = [elementen objectAtIndex:indexPath.row];
return Cell;
}
return NULL;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 200;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.Invulling.dataSource = self;
self.Invulling.delegate = self;
elementen = [[NSMutableArray alloc]init];
if(self.Categorien==tableView) {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = selectedCell.textLabel.text;
PFQuery *query = [PFQuery queryWithClassName:cellText];
[query selectKeys:#[#"Naam"]];
NSArray *result = [query findObjects];
for (PFObject *object in result) {
NSString *naam = object[#"Naam"];
if(![elementen containsObject:naam]) {
[elementen addObject:naam];
}
}
}
[self.Invulling setHidden:FALSE];
[self.Invulling reloadData];
}
end
Now, the problem is that the reloadData method does not work correctly. For example: if I press the first cell from the first tableview (Categorien), then nothing happens. But when I click another cell, the second tableview (Invulling) gets loaded with the results from the first cell.
you have to use didSelectRowAtIndexPath not didDeselectRowAtIndexPath method
Also look up some tutorial on debugging, you could have known that the method is not
being called if you have added breakpoints
You are using
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:
Instead, use
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
there is a strange problem I have not met ever
there is an array() including some custom object named MyClass parsed by JSONKit;
when I keep scrolling the tableview the memory will keeping increasing too.
but when replace
cell.textLabel.text = myclass.name;
with
cell.textLabel.text = #"cool";
or
cell.textLabel.text = [NSString stringWithFormate:#"a-%d", indexPath.row];
it's ok the memory with keep stable
but if I use
cell.textLabel.text = [NSString stringWithFormate:#"a-%#-i",myclass.name, indexPath.row];
it also keep increasing;
It will drive my crazy!!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Singers";
OMTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
MyClass *myclass = [self.data objectAtIndex:indexPath.row];
if (cell == nil){
cell = [[[OMTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
}
cell.textLabel.text = myclass.name;
return cell;
}
MyClass
there is two class one Base another inherit
Base:
#interface OMBase : NSObject {
NSMutableDictionary *data;
NSString *name;
NSArray *keys;
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, copy) NSMutableDictionary *data;
#implementation OMBase
#synthesize data, name;
- (void)setData:(NSMutableDictionary *)adata{
if (data){
[data release];
data = nil;
}
data = [adata mutableCopy];
}
- (void)dealloc{
if (keys){
[keys release];
}
[data release];
[super dealloc];
}
- (id)init{
if (self = [super init]){
self.data = [[[NSMutableDictionary alloc] initWithCapacity:20] autorelease];
}
return self;
}
inherit:
#import "OMBase.h"
#interface OMLyric : OMBase
- (NSString *)songid;
- (NSString *)content;
#import "OMLyric.h"
#implementation OMLyric
- (NSString *)songid{
return [data objectForKey:#"songid"];
}
- (NSString *)content{
return [data objectForKey:#"content"];
}
Seems like your myclass.name getter returns a new allocated object. We can't say more without seeing myclass.
I think I'm not getting the handle on address book and UITableView, or maybe I'm just making it simpler than it is.
here is my .h file:
#interface Contacts : UITableViewController <ABPeoplePickerNavigationControllerDelegate> {
NSMutableArray *menuArray;
NSString *firstName;
NSString *lastName;
UIButton *addcontact;
}
#property (nonatomic, retain) NSMutableArray *menuArray;
#property (nonatomic, strong) UIButton *addcontact;
#property (nonatomic, strong) NSString *firstName;
#property (nonatomic, strong) NSString *lastName;
-(void)showPeoplePickerController;
#end
And my .m file:
-(IBAction)addcontact:(id)sender {
ABPeoplePickerNavigationController *peoplePicker=[[ABPeoplePickerNavigationController alloc] init];
[peoplePicker setPeoplePickerDelegate:self];
[self presentModalViewController:peoplePicker animated:YES]; }
- (void)viewDidLoad
{
menuArray = [[NSMutableArray alloc] init];
[super viewDidLoad];
}
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
firstName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
[menuArray addObject:firstName];
lastName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
[menuArray addObject:lastName];
[self dismissModalViewControllerAnimated:YES];
return NO;}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [menuArray 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];
}
NSString *cellValue = [menuArray objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
I hope someone could help me with it, I'm fairley new to UITableViews and Addressbooks :)
For performance purposes (not to mention animation purposes), UITableView does not automatically update itself whenever the data source changes.
Try adding [myTableView reloadData]; after you add the first and last name to the arrays (or in viewWillAppear: