UITableView with Section, IndexList and Search - ios

I have added my delegate method and
I have a UITableView with a list of names. It has sections with an alphabetical index on the right hand side (see picture).
My program crashes whenever I enter a first character in the search field. I get the following error:
UpdateSearchResultsForSearchController
[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
Understand I am trying to access an empty array, in the method UpdateSearchResultsForSearchController.
The program crashes in the last line of the method.
[((UITableViewController *)self.searchController.searchResultsController).tableView reloadData];
Here is the header
#import <UIKit/UIKit.h>
#import "EmployeeDatabase.h"
#interface EmployeeListViewController : UITableViewController<UISearchResultsUpdating, UISearchBarDelegate>
#property (nonatomic, strong) NSMutableArray *employees;
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) NSMutableArray *tableSections;
#property (nonatomic, strong) NSMutableArray *tableSectionsAndItems;
#end
and here is the implementation
#import "EmployeeListViewController.h"
#import "EmployeeDetailViewController.h"
#implementation EmployeeListViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeTableContent];
[self initializeSearchController];
[self styleTableView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Initialization methods
- (void)initializeTableContent {
self.employees = [EmployeeDatabase getEmployees];
self.tableSections = [NSMutableArray array];
self.tableSectionsAndItems = [NSMutableArray array];
for (employee *name in self.employees) {
NSString *key = [[name.lstNme substringToIndex: 1] uppercaseString];
if ([self.tableSections containsObject:key] == false) {
[self.tableSections addObject:key];
NSMutableArray *tmpArray = [NSMutableArray array];
[tmpArray addObject:name.fulNme];
NSMutableDictionary *tmpDictionary = [NSMutableDictionary dictionaryWithObject:tmpArray forKey:key];
[self.tableSectionsAndItems addObject:tmpDictionary];
} else {
NSMutableArray *tmpArray = [NSMutableArray array];
NSUInteger index = [self.tableSections indexOfObject:key];
NSMutableDictionary *tmpDictionary = [self.tableSectionsAndItems objectAtIndex:index];
tmpArray = [tmpDictionary objectForKey:key];
[tmpArray addObject:name.fulNme];
[self.tableSectionsAndItems removeObjectAtIndex:index];
[self.tableSectionsAndItems addObject:tmpDictionary];
}
}
}
- (void)initializeSearchController {
//instantiate a search results controller for presenting the search/filter results (will be presented on top of the parent table view)
UITableViewController *searchResultsController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
searchResultsController.tableView.dataSource = self;
searchResultsController.tableView.delegate = self;
//instantiate a UISearchController - passing in the search results controller table
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
//this view controller can be covered by theUISearchController's view (i.e. search/filter table)
self.definesPresentationContext = YES;
//define the frame for the UISearchController's search bar and tint
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x,
self.searchController.searchBar.frame.origin.y,
self.searchController.searchBar.frame.size.width, 44.0);
self.searchController.searchBar.tintColor = [UIColor whiteColor];
//add the UISearchController's search bar to the header of this table
self.tableView.tableHeaderView = self.searchController.searchBar;
//this ViewController will be responsible for implementing UISearchResultsDialog protocol method(s) - so handling what happens when user types into the search bar
self.searchController.searchResultsUpdater = self;
//this ViewController will be responsisble for implementing UISearchBarDelegate protocol methods(s)
self.searchController.searchBar.delegate = self;
}
- (void)styleTableView {
[[self tableView] setSectionIndexColor:[UIColor colorWithRed:100.0f/255.0f green:100.0f/255.0f blue:100.0f/255.0f alpha:1.0f]];
[[self tableView] setSectionIndexBackgroundColor:[UIColor colorWithRed:230.0f/255.0f green:230.0f/255.0f blue:230.0f/255.0f alpha:1.0f]];
}
#pragma mark - UITableViewDataSource methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.tableSections count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSDictionary *sectionItems = [self.tableSectionsAndItems objectAtIndex:section];
NSArray *namesForSection = [sectionItems objectForKey:[self.tableSections objectAtIndex:section]];
return [namesForSection count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [self.tableSections objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellReuseId = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellReuseId];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellReuseId];
}
NSDictionary *sectionItems = [self.tableSectionsAndItems objectAtIndex:indexPath.section];
NSArray *namesForSection = [sectionItems objectForKey:[self.tableSections objectAtIndex:indexPath.section]];
cell.textLabel.text = [namesForSection objectAtIndex:indexPath.row];
//show accessory disclosure indicators on cells only when user has typed into the search box
if(self.searchController.searchBar.text.length > 0) {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
#pragma mark - UITableViewDelegate methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *sectionItems = [self.tableSectionsAndItems objectAtIndex:indexPath.section];
NSArray *namesForSection = [sectionItems objectForKey:[self.tableSections objectAtIndex:indexPath.section]];
NSString *selectedItem = [namesForSection objectAtIndex:indexPath.row];
//Log
NSLog(#"User selected %#", selectedItem);
}
//#pragma Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
employee *employee = self.employees[indexPath.row];
EmployeeDetailViewController *employeeDetailViewController = segue.destinationViewController;
employeeDetailViewController.detailItem = employee;
}
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
//only show section index titles if there is no text in the search bar
if(!(self.searchController.searchBar.text.length > 0)) {
NSArray *indexTitles = self.tableSections;
//HERE
//*indexTitles = [Item fetchDistinctItemGroupsInManagedObjectContext:self.managedObjectContext];
return indexTitles;
} else {
return nil;
}
}
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
view.tintColor = [UIColor colorWithRed:100.0f/255.0f green:100.0f/255.0f blue:100.0f/255.0f alpha:1.0f];
UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view;
[header.textLabel setTextColor:[UIColor whiteColor]];
}
#pragma mark - UISearchResultsUpdating
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
//get search text from user input
NSString *searchText = [self.searchController.searchBar text];
//exit if there is no search text (i.e. user tapped on the search bar and did not enter text yet)
if(!([searchText length] > 0)) {
return;
}
//handle when there is search text entered by the user
else {
//based on the user's search, we will update the contents of the tableSections and tableSectionsAndItems properties
[self.tableSections removeAllObjects];
[self.tableSectionsAndItems removeAllObjects];
NSString *firstSearchCharacter = [searchText substringToIndex:1];
//handle when user taps into search bear and there is no text entered yet
if([searchText length] == 0) {
//self.tableSections = [[Item fetchDistinctItemGroupsInManagedObjectContext:self.managedObjectContext] mutableCopy];
//self.tableSectionsAndItems = [[Item fetchItemNamesByGroupInManagedObjectContext:self.managedObjectContext] mutableCopy];
}
//handle when user types in one or more characters in the search bar
else if(searchText.length > 0) {
//the table section will always be based off of the first letter of the group
NSString *upperCaseFirstSearchCharacter = [firstSearchCharacter uppercaseString];
self.tableSections = [[[NSArray alloc] initWithObjects:upperCaseFirstSearchCharacter, nil] mutableCopy];
//there will only be one section (based on the first letter of the search text) - but the property requires an array for cases when there are multiple sections
//NSDictionary *namesByGroup = [Item fetchItemNamesByGroupFilteredBySearchText:searchText ////inManagedObjectContext:self.managedObjectContext];
//self.tableSectionsAndItems = [[[NSArray alloc] initWithObjects:namesByGroup, nil] mutableCopy];
}
//now that the tableSections and tableSectionsAndItems properties are updated, reload the UISearchController's tableview
[((UITableViewController *)self.searchController.searchResultsController).tableView reloadData];
}
}
#pragma mark - UISearchBarDelegate methods
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self.tableSections removeAllObjects];
[self.tableSectionsAndItems removeAllObjects];
//self.tableSections = [[Item fetchDistinctItemGroupsInManagedObjectContext:self.managedObjectContext] mutableCopy];
//self.tableSectionsAndItems = [[Item fetchItemNamesByGroupInManagedObjectContext:self.managedObjectContext] mutableCopy];
}
#end

The problem is that, your are removing all objects at this line
[self.tableSectionsAndItems removeAllObjects];
and you have commented the lines, which again feels that array, just above the lines which you mentioned in your question. so, uncomment the following lines
//NSDictionary *namesByGroup = [Item fetchItemNamesByGroupFilteredBySearchText:searchText ////inManagedObjectContext:self.managedObjectContext];
//self.tableSectionsAndItems = [[[NSArray alloc] initWithObjects:namesByGroup, nil] mutableCopy];
And in numberOfRows Method, you are accessing the object at index on empty array that leads to crash.
[self.tableSectionsAndItems objectAtIndex:section];
So, uncomment those two lines above, in the following method and it will fix.
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController
Try and share your results.

Related

How to make textfield input view as search bar?

I have tried to get proper solution ,but I can't any programmers please give me a idea how to make.
1.is it possible to make uitextfield as uisearchbar?
UISearchBar *search=[[UISearchBar alloc]init];
search.delegate=self;
[_txtLocation setInputView:search];
2.While user types the values I need show it as overlay at the bottom of the text field...
3.Please help me to find out the solution..
To make Text Field work like Search Bar implement - (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string delegate method of UITextField. So basically, you need to implement AutoComplete feature and this how you do it.
To detect which textfield is triggered use assign tag to the textfield.
In your ViewController.h file:
#interface ViewController :
<UIViewController<UITextFieldDelegate,UITableViewDataSource, UITableViewDelegate>
{
UITableView *autocompleteTableView;
UITextField * searchtextField1;
UITextField * searchtextField2;
NSMutableArray *autoCompleteList;
NSMutableArray *initalList;
}
In your ViewController.m file:
- (void)viewDidLoad {
searchtextField1 = [[UITextField alloc]
initWithFrame:CGRectMake(5,0, 245, 33)];
searchtextField2.tag = 2;
searchtextFeild1.tag = 1;
searchtextField.placeholder = #"eg: make up";
searchtextField.textColor = [UIColor whiteColor];
//[imageView addSubview:searchtextField];
//[self.view addSubview:imageView];
autoCompleteList = [[NSMutableArray alloc] init];
searchtextField1.delegate = self;
searchtextField2.delegate = self;
autocompleteTableView = [[UITableView alloc]init];
if(screenRect.size.height == 568)
{
float X_Co_tbl = (self.view.frame.size.width - 271)/2;
[autocompleteTableView setFrame:CGRectMake(X_Co_tbl, 105, 271, 120)];
}
else if (screenRect.size.width == 414)
{
float X_Co_tbl = (self.view.frame.size.width - 281)/2;
[autocompleteTableView setFrame:CGRectMake(X_Co_tbl, 145, 281, 120)];
}
else if(screenRect.size.width == 375)
{
float X_Co_tbl = (self.view.frame.size.width - 281)/2;
[autocompleteTableView setFrame:CGRectMake(X_Co_tbl, 125, 281, 120)];
}
else
{
float X_Co_tbl = (self.view.frame.size.width - 271)/2;
[autocompleteTableView setFrame:CGRectMake(X_Co_tbl, 95, 271, 120)];
}
autocompleteTableView.delegate = self;
autocompleteTableView.dataSource = self;
autocompleteTableView.scrollEnabled = YES;
autocompleteTableView.hidden = YES;
[self.view addSubview:autocompleteTableView];
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
autocompleteTableView.hidden = YES;
return YES;
}
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
autocompleteTableView.hidden = NO;
if (textField.tag == 1) {
/// Initialize your array for searchTextFeild1;
initialList = [[NSMutableArray alloc]initWithObjects:#"Face wash",#"Morning face wash",#"Cleanser", nil];
}
if (textField.tag == 2) {
/// Initialize your array for searchTextFeild2;
initialList = [[NSMutableArray alloc]initWithObjects:#"Face wash",#"Morning face wash",#"Cleanser", nil];
}
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring
stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
}
/// You make Text Field work as Search Bar here
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring {
// Put anything that starts with this substring into the autocompleteUrls array
// The items in this array is what will show up in the table view
[autoCompleteList removeAllObjects];
for(NSString *curString in initialList) {
//NSRange substringRange = [curString rangeOfString:substring];
if ([curString rangeOfString:substring options:NSCaseInsensitiveSearch].location != NSNotFound) {
[autoCompleteList addObject:curString];
}
}
[autocompleteTableView reloadData];
}
#pragma mark UITableViewDataSource methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
return autoCompleteList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = #"AutoCompleteRowIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier];
}
cell.textLabel.text = [autoCompleteList objectAtIndex:indexPath.row];
return cell;
}
#pragma mark UITableViewDelegate methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
searchtextField.text = selectedCell.textLabel.text;
autocompleteTableView.hidden = YES;
[self goPressed];
}
In .h file
#import <UIKit/UIKit.h>
#interface SEMainVC : UIViewController <UITextFieldDelegate>{
NSMutableArray *dummyArray;
NSMutableArray *searchArray;
NSString *searchTextString;
}
#property (weak, nonatomic) IBOutlet UITextField *searchTextField;
#property (weak, nonatomic) IBOutlet UITableView *contentTableView;
- (void) setupData;
#end
In .m file
#interface SEMainVC ()
#end
#implementation SEMainVC
- (void)viewDidLoad
{
[super viewDidLoad];
//set the selector to the text field in order to change its value when edited
[self.searchTextField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
//here you set up the methods to search array and reloading the tableview
[self setupData];
[self updateSearchArray];
[self.contentTableView reloadData];
}
//setting up the data sourch for the mutable array
- (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 [searchArray 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];
}
cell.textLabel.text = [[searchArray objectAtIndex:indexPath.row] objectForKey:#"name"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"DummyDetail" sender:[NSNumber numberWithInt:indexPath.row]];
}
#pragma mark - Search Methods
-(void)textFieldDidChange:(UITextField*)textField
{
searchTextString = textField.text;
[self updateSearchArray];
}
//update seach method where the textfield acts as seach bar
-(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.contentTableView reloadData];
}
#pragma mark - Table view delegate
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(NSNumber*)indexNumber
{
if([[segue identifier] isEqualToString:#"DummyDetail"]){
NSInteger index = [indexNumber integerValue];
SEDetailVC *dummyDetail = [segue destinationViewController];
dummyDetail.dummyImageString = [[searchArray objectAtIndex:index] objectForKey:#"image"];
dummyDetail.dummyTextString = [[searchArray objectAtIndex:index] objectForKey:#"description"];
dummyDetail.title = [[searchArray objectAtIndex:index] objectForKey:#"name"];
}
}
- (void)viewDidUnload {
[self setSearchTextField:nil];
[self setContentTableView:nil];
[super viewDidUnload];
}
#end

UISearchBar search not clearing old cells

I'm trying to implement a UISearchBar in a custom UITableViewController and done programmatically (not using IB). I got the search function to work and return the correct fields, but it is displaying the searched cells over the full list cells:
As you can see, the new searched field is scrollable and selectable. Its just not removing the old cells.
here is my .h file:
#interface TestTableViewController : UITableViewController <UISearchBarDelegate, UISearchDisplayDelegate>
#property (strong, nonatomic) NSArray *boundaries;
#end
.m file:
#import "TestTableViewController.h"
#import "Boundary.h"
#interface TestTableViewController ()
#property (strong, nonatomic) UISearchDisplayController *searchController;
#property (strong, nonatomic) NSMutableArray *filteredBoundaries;
#end
#implementation TestTableViewController
-(instancetype) initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
self.filteredBoundaries = [NSMutableArray array];
}
return self;
}
-(void)viewDidLoad {
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:TRUE selector:#selector(caseInsensitiveCompare:)];
NSArray *sortDescriptors = #[sortDescriptor];
self.boundaries = [self.boundaries sortedArrayUsingDescriptors:sortDescriptors];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
searchBar.delegate = self;
searchBar.placeholder = #"Search Fields";
searchBar.showsCancelButton = TRUE;
self.tableView.tableHeaderView = searchBar;
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
}
// ------------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark Setup Filter Data Source
-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope {
[self.filteredBoundaries removeAllObjects];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
self.filteredBoundaries = [NSMutableArray arrayWithArray:[self.boundaries filteredArrayUsingPredicate:predicate]];
}
// ------------------------------------------------------------------------------------------------------
#pragma mark -
#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 self.filteredBoundaries.count;
}
else {
return self.boundaries.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) {
Boundary *boundary = [self.filteredBoundaries objectAtIndex:indexPath.row];
cell.textLabel.text = boundary.name;
cell.textLabel.textColor = [UIColor blackColor];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
}
else {
Boundary *boundary = [self.boundaries objectAtIndex:indexPath.row];
cell.textLabel.text = boundary.name;
cell.textLabel.textColor = [UIColor blackColor];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.userInteractionEnabled = TRUE;
}
return cell;
}
// ------------------------------------------------------------------------------------------------------
#pragma mark -
#pragma mark UISearchDisplayController Delegates
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString scope:[[self.searchController.searchBar scopeButtonTitles] objectAtIndex:self.searchController.searchBar.selectedScopeButtonIndex]];
return TRUE;
}
#end
And how I call the table view:
TestTableViewController *tableViewController = [[TestTableViewController alloc] initWithStyle:UITableViewStylePlain];
tableViewController.boundaries = [group.boundaries allObjects];
tableViewController.contentSizeForViewInPopover = POPOVER_SIZE;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tableViewController];
navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
navController.navigationBar.barStyle = UIBarStyleBlack;
self.myPopoverController = [[UIPopoverController alloc] initWithContentViewController:navController];
self.myPopoverController.delegate = self;
[self.myPopoverController presentPopoverFromRect:button.frame inView:button.superview permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Any ideas what I might be doing wrong or missing?
The problem is that UISearchDisplayController is using another UITableView rather than the view controller's own. You can verify that by logging tableView in -tableView:cellForRowAtIndexPath:.
You can use a UISearchBar without a UISearchDisplayController, to have more control over search and display logic.
Also, if your app doesn't support any version prior to iOS 8, consider using UISearchController. I haven't tried it but it seems to give you more control. Check a sample UISearchDisplayControllerhas been deprecated in iOS 8.
Try this
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 41.0)];
[self.view addSubview:searchBar];
searchBar.delegate=self;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
if (isSearching) {
return [filteredContentList count];
}
else {
return [titlearray count];
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (isSearching)
{
cell.nameLabel.text = [filteredContentList objectAtIndex:indexPath.row];
cell.thumbnailImageView.image =[filteredImgArray objectAtIndex:indexPath.row];
}
else
{
cell.thumbnailImageView.image = [imagearray objectAtIndex:indexPath.row];
cell.nameLabel.text = [titlearray objectAtIndex:indexPath.row];
}
return cell;
}
- (void)searchTableList {
NSString *searchString = searchBar.text;
for (int i=0; i<titlearray.count; i++) {
NSString *tempStr=[titlearray objectAtIndex:i];
NSComparisonResult result = [tempStr compare:searchString options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchString length])];
if (result == NSOrderedSame)
{
[filteredContentList addObject:tempStr];
[filteredImgArray addObject:[imagearray objectAtIndex:i]];
}
}
}
#pragma mark - Search Implementation
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
isSearching = YES;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSLog(#"Text change - %d",isSearching);
//Remove all objects first.
[filteredContentList removeAllObjects];
[filteredImgArray removeAllObjects];
if([searchText length] != 0) {
isSearching = YES;
[self searchTableList];
//tblContentList.hidden=NO;
}
else {
isSearching = NO;
// tblContentList.hidden=YES;
}
[tblContentList reloadData];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Cancel clicked");
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
NSLog(#"Search Clicked");
[self searchTableList];
}
I hope it's help for you
You should implement correct datasource.
Create new array of items for filtered data for first.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger count = ([filteredItems count] > 0) ? [filteredItems count] : [self.allItems count];
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier: #"id"];
MyCustomItem *item = ([filteredItems count] > 0) ? filteredItems[indexPath.row] : self.allItems[indexPath.row];
[self configureCell:cell forItem:item];
return cell;
}
Configure searching:
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchText = searchController.searchBar.text;
if ([searchText length] == 0)
{
[filteredItems removeAllObjects];
[self.tableView reloadData];
return;
}
NSMutableArray *searchResults = [self.allItems mutableCopy];
// SKIP ALL BODY OF SEARCHING
filteredPeoples = searchResults;
[self.tableView reloadData];
}
Will work pretty.
IOS 8 delegate has been deprecated not sure if that's the problem.
The method
here's [a link]https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UISearchDisplayDelegate_Protocol/index.html#//apple_ref/occ/intfm/UISearchDisplayDelegate/searchDisplayControS 8 delegate has been deprecated not sure if that's the problem.
The method
try this property instead
#property(nonatomic, assign) id< UISearchResultsUpdating > searchResultsUpdater
another better link [a link]https://developer.apple.com/library/ios/samplecode/TableSearch_UISearchController/Listings/TableSearch_obj_c_TableSearch_APLResultsTableController_m.html

iOS search bar not showing results

*Update: This actually works, the style for my custom cell hasn't come across and so the cell looks blank. How then do I get the searchResultsTableView to use my custom cell?
I have implemented a search bar in my table view. Searching, filtering all work when I debug, but when I enter characters into the search bar, the results do not load or show. This is everything I'm doing:
#interface InviteTableViewController ()<UIAlertViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>
#property(nonatomic, strong) NSNumber *contactsCount;
#property(nonatomic, strong) InviteTableViewCell *selectedCell;
#property(strong, nonatomic) NSMutableArray *filteredContactArray;
#property (weak, nonatomic) IBOutlet UISearchBar *contactsSearchBar;
#end
#implementation InviteTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void) extractAllContacts: (ABAddressBookRef) addressBookRef{
NSMutableArray *contactsArray = [NSMutableArray array];
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBookRef);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBookRef);
for(int i = 0; i < numberOfPeople; i++){
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
if(firstName){
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(emails); i++) {
NSString *email = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(emails, i);
MyUser *amUser = [[MyUser alloc] init];
amUser.email =email;
NSString *fullName =[NSString stringWithFormat:#"%# %#",firstName, (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty))];
amUser.fullName = fullName;
[contactsArray addObject:amUser];
}
}
}
NSLog(#"================================count ============= %d", [contactsArray count]);
contactsArray = [contactsArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSDate *first = [(MyUser*) a fullName];
NSDate *second = [(MyUser*)b fullName];
return [first compare:second];
}];
self.inviteContactsArray = contactsArray;
self.filteredContactArray = [NSMutableArray arrayWithCapacity:[contactsArray count]];
[self.tableView reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
_contactsCount = [NSNumber numberWithInt:0];
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
if (granted) {
[self extractAllContacts: addressBookRef];
[self.tableView reloadData];
} else {
NSString *message = [NSString stringWithFormat:#"You have not given permission to use your address book. Please allow in settings "];
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Enable Contacts" message:message delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// The user has previously given access, add the contact
[self extractAllContacts:addressBookRef];
}
else {
// The user has previously denied access
// Send an alert telling user to change privacy setting in settings app
}
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [self.filteredContactArray count];
} else {
return [self.inviteContactsArray count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"InviteCell";
InviteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if ( cell == nil ) {
cell = [[InviteTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
MyUser *person = nil;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
person = [self.filteredContactArray objectAtIndex:[indexPath row]];
NSMutableArray *tempArray = self.filteredContactArray;
}
else
{
person = [self.inviteContactsArray objectAtIndex:[indexPath row]];
}
//InviteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
person = [self.inviteContactsArray objectAtIndex:indexPath.row];
cell.nameLabel.text = person.fullName;
cell.emailLabel.text = person.email;
return cell;
}
#pragma mark Content Filtering
-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
// Update the filtered array based on the search text and scope.
// Remove all objects from the filtered search array
[self.filteredContactArray removeAllObjects];
// Filter the array using NSPredicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.fullName contains[c] %#",searchText];
self.filteredContactArray = [NSMutableArray arrayWithArray:[self.inviteContactsArray filteredArrayUsingPredicate:predicate]];
}
#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;
}
#end
This is what it looks like:
Agree with #rdelmar.
BUT There is a kind of tricky behavior in TableView, if you change the code in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
....
InviteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
....
}
to
InviteTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if added the prefix "self." your code should works fine.
and
if ( cell == nil )
{
cell = [[InviteTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
is unnecessary. it will just create a standard "Subtitle Cell" for you that seems not you want, just remove them.
If you want to use the same cell for your main table and the search results table, you should make the cell in a xib (or you could do it entirely in code). In viewDidLoad, register the nib for both table views,
- (void)viewDidLoad {
[super viewDidLoad];
[self.searchDisplayController.searchResultsTableView registerNib:[UINib nibWithNibName:#"InviteTableViewCell" bundle:nil] forCellReuseIdentifier:#"InviteCell"];
[self.tableView registerNib:[UINib nibWithNibName:#"InviteTableViewCell" bundle:nil] forCellReuseIdentifier:#"inviteCell"];
}
In cellForRowAtIndexPath, you can do something like this,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
InviteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"InviteCell" forIndexPath:indexPath];
MyUser *person = ([tableView isEqual:self.tableView])? self.inviteContactsArray[indexPath.row] : self.filteredContactArray[indexPath row];
cell.nameLabel.text = person.fullName;
cell.emailLabel.text = person.email;
return cell;
}
If you've already setup your cell in the storyboard, you can copy and paste it into an empty xib file, so you don't have to set it up all over again. You can delete the cell from your storyboard table view since you will be getting the cell from the xib file instead.
Below line in viewdidload should do the trick
self.searchDisplayController.searchResultsTableView.rowHeight = self.tableView.rowHeight

Adding additional data to inner array with sorted outer array

I have a plist with contacts: the root is an array, items 0-150 are dictionaries, each dictionary is a single contact with a "name", "number", and "email" string.
The code below sorts the contacts alphabetically into sections based upon the "name" string. Then uses the inner array to populate the cells for each section. I then pass the name from the inner array to my detail view.
However, I can not figure out how to pass the correct number and email for each contact into the detail view. I've been working on this issue for a long while and can not find a solution.
#interface ContactsViewController ()
-(void)configureSectionData;
#end
#implementation ContactsViewController
#synthesize tableData;
#synthesize collation;
#synthesize outerArray;
#synthesize indexTitlesArray, namesDictionary;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - Table view methods
-(void)configureSectionData {
NSUInteger sectionTitlesCount = [collation.sectionTitles count];
self.outerArray = [NSMutableArray arrayWithCapacity:sectionTitlesCount];
for (NSUInteger index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *array = [NSMutableArray array];
[self.outerArray addObject:array];
}
for (NSString *nameString in tableData)
{
NSInteger sectionNumber = [collation sectionForObject:nameString collationStringSelector:#selector(lowercaseString)];
NSMutableArray *sectionNames = [outerArray objectAtIndex:sectionNumber];
[sectionNames addObject:nameString];
}
for (NSUInteger index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *namesForSection = [outerArray objectAtIndex:index];
NSArray *sortedNamesForSection = [collation sortedArrayFromArray:namesForSection collationStringSelector:#selector(lowercaseString)];
[self.outerArray replaceObjectAtIndex:index withObject:sortedNamesForSection];
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.collation.sectionTitles count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *theLetter = [self.collation.sectionTitles objectAtIndex:section];
if (![theLetter isEqualToString:#"#"]) {
NSString *titleString = [NSString stringWithFormat:#"%#", theLetter];
return titleString;
}
return nil;
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.collation.sectionTitles;
}
-(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [self.collation sectionForSectionIndexTitleAtIndex:index];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *innerArray = [self.outerArray objectAtIndex:section];
return [innerArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// Get the inner array for this section
NSArray *innerArray = [self.outerArray objectAtIndex:indexPath.section];
// Get the name from the inner array
NSString *theName = [innerArray objectAtIndex:indexPath.row];
cell.textLabel.text = theName;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainiPhoneStoryboard" bundle:nil];
DetailViewController *detailView = (DetailViewController *)[storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
// Get the inner array for this section
NSArray *innerArray = [self.outerArray objectAtIndex:indexPath.section];
// Get the name from the inner array
NSString *tmpname = [innerArray objectAtIndex:indexPath.row];
detailView.lblname = tmpname;
[self presentViewController:detailView animated:YES completion:nil];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.namesDictionary = [NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"contacts" ofType:#"plist"]];
self.tableData = [namesDictionary valueForKey:#"name"];
self.collation = [UILocalizedIndexedCollation currentCollation];
[self configureSectionData];
}
Since you're populating your table from an array of just the names from your plist, you'll have to search that array using the name to find the dictionary that it belongs to, so you can pass that to the detail view controller (you would need to create a property in your detail view controller, passedInDictionary in my example):
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainiPhoneStoryboard" bundle:nil];
DetailViewController *detailView = (DetailViewController *)[storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
// Get the inner array for this section
NSArray *innerArray = [self.outerArray objectAtIndex:indexPath.section];
// Get the name from the inner array
NSString *tmpname = [innerArray objectAtIndex:indexPath.row];
NSInteger indx = [self.namesDictionary indexOfObjectPassingTest:^BOOL(NSDictionary *dict, NSUInteger idx, BOOL *stop) {
return [dict[#"name"] isEqualToString:tmpname];
}];
NSDictionary *dict = self.namesDictionary[indx];
detailView.passedInDictionary = dict;
[self presentViewController:detailView animated:YES completion:nil];
}

Updating of a Mutable Array

I have a mutable Array in a Tableview, this is populated on View did load from an SQLite database, However this database changes as it is a favourites database for products in my app.
When a user selects one of the items in the tableview (The user then goes to a detail view, with the info from the database) the user can then select to remove it from the favourites (database) when the user then presses back in the navigation bar, the item is still there, I've tried tableview reload on view did appear, and view will appear but that doesn't help,
Can anyone shed any light on this??
Many thanks,
Andrew
Here is my code:
FavTableViewController.h:
#interface FavTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView *Table;
}
#property (nonatomic, strong) UITableView *Table;
#property (nonatomic, strong) NSArray *cats;
#property (nonatomic, strong) IBOutlet UISearchBar *searchBar;
#property (nonatomic, strong) UISearchDisplayController *searchDisplayController;
#property (nonatomic, strong) NSMutableArray *filteredListContent;
#property (nonatomic, strong) NSMutableArray *listContent;
#property (nonatomic, strong) NSArray *everything;
#property (nonatomic, copy) NSString *savedSearchTerm;
#property (nonatomic) NSInteger savedScopeButtonIndex;
#property (nonatomic) BOOL searchWasActive;
#property (nonatomic, strong) NSString *cellText;
-(void) refresh;
#end
FavTableViewController.m:
#import "FavTableViewController.h"
#import "DBFavAdapter.h"
#import "MenuData.h"
#import "DBAdapter.h"
#import "DetailViewController.h"
#import "ConsoleDetailController.h"
#import "EffectDetailViewController.h"
#import "DimmersDetailController.h"
#import "ConventionalController.h"
#import "ProDetailViewController.h"
#implementation FavTableViewController
#synthesize filteredListContent, savedSearchTerm, savedScopeButtonIndex, searchWasActive, searchBar, searchDisplayController, listContent, everything, cellText, cats, Table;
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
listContent = [[NSMutableArray alloc] init];
}
return self;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
NSLog(#"Did Load");
[super viewDidLoad];
everything = [[DBFavAdapter allProducts] mutableCopy];
for (NSDictionary *dict in everything) {
[listContent addObject: [dict objectForKey:#"Title"]];
}
// create a filtered list that will contain products for the search results table.
self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.listContent count]];
// restore search settings if they were saved in didReceiveMemoryWarning.
if (self.savedSearchTerm)
{
[self.searchDisplayController setActive:self.searchWasActive];
[self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
[self.searchDisplayController.searchBar setText:savedSearchTerm];
self.savedSearchTerm = nil;
}
// [self.tableView reloadData];
self.Table.scrollEnabled = YES;
self.navigationItem.title = #"Favourites";
// cats = [DBFavAdapter allCategories];
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.filteredListContent = nil;
NSLog(#"Unload");
}
- (void)viewWillAppear:(BOOL)animated {
NSLog(#"View will Appear");
[Table reloadData];
NSLog(#"Everything: %#",everything);
NSLog(#"list Content: %#",listContent);
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
NSLog(#"View did Appear");
[super viewDidAppear:animated];
NSLog(#"list Content appeared: %#",listContent);
[Table reloadData];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(#"Did dissapear");
// 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];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#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 [self.filteredListContent count];
}
else {
return [self.listContent count];
}
NSLog(#"Rows %i",[self.listContent count]);
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// NSDictionary *dictionary = [self.tableDataSource objectAtIndex:indexPath.row];
if (tableView == searchDisplayController.searchResultsTableView)
{
cellText = [self.filteredListContent objectAtIndex:indexPath.row];
}
else
{
cellText = [self.listContent objectAtIndex:indexPath.row];
}
// NSString *cellText = [self.listContent objectAtIndex:indexPath.row];
UIFont *cellFont = [UIFont fontWithName:#"Heiti TC" size:17.0];
CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
return labelSize.height + 30;
}
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = 1;
return row;
}
- (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];
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont fontWithName:#"Heiti TC" size:17.0];
}
// Configure the cell...
if (tableView == searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.filteredListContent objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = [self.listContent objectAtIndex:indexPath.row];
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *selectedItem;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
selectedItem = [self.filteredListContent objectAtIndex:indexPath.row];
}
else
{
selectedItem = [self.listContent objectAtIndex:indexPath.row];
}
// Is the selection a category?
// NSArray *cats = [DBAdapter allCategories];
__block BOOL cat = NO;
[cats enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([(NSString*)obj isEqualToString:selectedItem]) {
cat = YES;
*stop = YES;
}
}];
if (cat) { // the user's selection was a category
// NSLog(#"Selected item was a category");
}
else {
NSArray *mans = [DBAdapter allManufacturers];
__block BOOL man = NO;
[mans enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([(NSString*)obj isEqualToString:selectedItem]) {
man = YES;
*stop = YES;
}
}];
if (man) { // the user's selection was a manufacturer
// NSLog(#"Selected item was a manufacturer");
} else {
// the user's selection was a product
// Find selectedItem in products
__block NSDictionary *selectedRow = nil;
[self.everything enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
//everything is an array of dictionaries
if ([(NSString*)[(NSDictionary*)obj objectForKey:#"Title"] isEqualToString:selectedItem]) {
selectedRow = (NSDictionary*)obj;
*stop = YES;
}
}];
MenuData *selectionData = [MenuData menuData];
selectionData.manufacturerID = [[selectedRow objectForKey:#"Manufacturer_id"] integerValue];
selectionData.categoryID = [[selectedRow objectForKey:#"Category_id"] integerValue];
selectionData.sCategoryID = [[selectedRow objectForKey:#"SubCategory_id"] integerValue];
selectionData.ssCategoryID = [[selectedRow objectForKey:#"SuperSubCategory_id"] integerValue];
NSString *selectedTitle = [selectedRow objectForKey: #"Title"]; // You probably already have this value from your search. Here for the sake of clarity.
NSDictionary *productDetails = [DBAdapter productDetails: selectedTitle forCurrentData: selectionData];
NSArray *allKeys = [productDetails allKeys];
// NSLog(#"values: %i", [allKeys count]);
for (NSString *key in allKeys) {
id value = [productDetails objectForKey:key];
if ([value isKindOfClass:[NSString class]]) {
// NSLog(#"key: %# value: %#", key, value);
}
}
NSInteger ViewNumber = [[productDetails objectForKey:#"View"] integerValue];
switch (ViewNumber) {
case 25: {
DetailViewController *dvController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:[NSBundle mainBundle]];
dvController.dictionary = productDetails;
[self.navigationController pushViewController:dvController animated:YES];
}
break;
case 18: {
EffectDetailViewController *edvController = [[EffectDetailViewController alloc] initWithNibName:#"EffectDetailView" bundle:[NSBundle mainBundle]];
edvController.dictionary = productDetails;
[self.navigationController pushViewController:edvController animated:YES];
}
break;
case 17: {
ConsoleDetailController *cdvController = [[ConsoleDetailController alloc] initWithNibName:#"ConsoleDetailController" bundle:[NSBundle mainBundle]];
cdvController.dictionary = productDetails;
[self.navigationController pushViewController:cdvController animated:YES];
}
break;
case 2: {
ConsoleDetailController *cdvController = [[ConsoleDetailController alloc] initWithNibName:#"ConsoleDetailController" bundle:[NSBundle mainBundle]];
cdvController.dictionary = productDetails;
[self.navigationController pushViewController:cdvController animated:YES];
}
break;
case 3: {
DimmersDetailController *ddvController = [[DimmersDetailController alloc] initWithNibName:#"DimmersDetailController" bundle:[NSBundle mainBundle]];
ddvController.dictionary = productDetails;
[self.navigationController pushViewController:ddvController animated:YES];
}
break;
case 12: {
ConventionalController *cController = [[ConventionalController alloc] initWithNibName:#"ConventionalController" bundle:[NSBundle mainBundle]];
cController.dictionary = productDetails;
[self.navigationController pushViewController:cController animated:YES];
}
break;
case 5: {
ProDetailViewController *pController = [[ProDetailViewController alloc] initWithNibName:#"ProDetailViewController" bundle:[NSBundle mainBundle]];
pController.dictionary = productDetails;
[self.navigationController pushViewController:pController animated:YES];
}
break;
}
}
}
}
#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.
*/
for (NSString *product in listContent)
{
//Edit AD - NS Range works instead of NSComparisonResult
NSRange result = [product rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
if (result.location != NSNotFound)
{
[self.filteredListContent addObject:product];
}
/*
// NSComparisonResult result = [product compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame)
{
[self.filteredListContent addObject:product];
}
*/
}
}
#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;
}
- (void)refresh {
NSLog(#"Refresh");
if([NSThread isMainThread])
{
[self.Table reloadData];
[self.Table setNeedsLayout];
[self.Table setNeedsDisplay];
}
else
{
[self performSelectorOnMainThread:#selector(refresh) withObject:nil waitUntilDone:YES];
}
}
#end
You have 2 options.
Remove the item from the listContent as well. This can be done via a delegate method that will be called from the child view controller when you delete the item.
Move your viewDidLoad functionality where listContents is generated from the database to viewWillAppear. This will cause listContents to read the database again, after the item was deleted and you hit the back button, this will also get called when the view first opens.

Resources