UISearchDisplayController and custom cell - iphone

I have implemented a UISearchDisplayController in the UITableViewController. The search is working, but the UISearhDisplayController creates a new tableView with a standard cell, and my tableView is using a custom cell. Another problem is that I use a segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
and the cells in searchResultsTableView are not triggering the segue..
How to display the search results with custom cell and segue working?
This is the codes:
...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView){
return [nameFilteredObj count];
} else {
return [sortedObj count];
}}
- (CustomCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"customCell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [[sortedObj objectAtIndex:indexPath.row] valueForKey:#"Name"];
} else {
cell.nameLabel.text = [[sortedObj objectAtIndex:indexPath.row] valueForKey:#"Name"];
cell.countryLabel.text = [[sortedObj objectAtIndex:indexPath.row] valueForKey:#"Country"];
cell.bottleImageView.image = [UIImage imageNamed:[[sortedObj objectAtIndex:indexPath.row] valueForKey:#"Image"]];
}
return cell;
}
//The codes for filtering the results and update of searchResultsTableView (not necessary for this question I think):
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[nameFilteredObj removeAllObjects];
for(NSDictionary *obj in sortedObj)
{
NSString *objName = [obj objectForKey:#"Name"];
NSRange range = [objName rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (range.location != NSNotFound) {
[nameFilteredObj addObject:obj];
}}}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
return NO;}
...
I'm using Storyboard as interface.

Actually very easy to do, but I found many complicated half-working solutions on the way. Use this easy piece and SearchResultsTableView is GONE:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
...
self.searchDisplayController.searchResultsTableView.hidden=YES;
return YES;
}

Related

tableview as a intelligence in iphone not working

I have a textfield and a tableview. User may select textfield data from tableview or any other data.but after entering user own data my tableview must disappear.how can i achieve this.if i use resign first responder did select rowmethod is not working in tableview.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
txtcity.text = selectedCell.textLabel.text;
}
-(void)hideKeyboard //this is my gesture recogniser method
{
autocompletetableview.hidden=true;//if i didn't use this statement it enter into didselectrow method
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
autocompleteTableView.hidden=YES;
if( textField == txtcity)
{
autocompleteTableView.hidden = NO;
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];// this method loads data into my tableview
return YES;
}
}
(BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
if([txtcity.text isEqualToString:#""])
{
autocompleteTableView.hidden=YES;
return YES;
}
else
autocompleteTableView.hidden=NO;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
return arr2.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] autorelease];
}
cell.textLabel.text = [[arr2 objectAtIndex:indexPath.row]objectForKey:#"Name"];
cell.textLabel.font=[UIFont boldSystemFontOfSize:12];
cell.textLabel.numberOfLines=0;
return cell;
}
if i use like this if i select row it doesn't enter into did select row at index path method. help me
i am not getting where i have to use resignfirstresponder
resignFirstResponder is used to dismiss the first responder ( keyboard in the case of UITextField). If you want the tableview to disappear set the hidden property to true or remove the tableview from the view hierarchy.
i.e;
[tableView setHidden:YES]
or
[tableView removeFromSuperview];
UPDATE:
If using gesture recognizer for checking on the tap on parent view, you can do the following so that the gesture method is not fired unnecessarily.
I'm assuming you are writing all this code in the view controller for the whole thing.
UITapGestureRecognizer *tapGe = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
tapGe.numberOfTapsRequired = 1;
tapGe.delegate =self;
[self.view addGestureRecognizer:tapGe]
Then implement the following method in the view controller (Make it conform to UIGestureRecognizerDelegate protocol):
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
If(touch.view==self.view){
return YES; //If its the main view accept the touch
}else{
return NO; //Otherwise(say tableview) don't consume the touch.
}
}
I think It's useful to you.I have used custom cell and I have give my working code here.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [mainDetaileArray count];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 115;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"ProductMerchantCell" owner:nil options:nil];
for (UIView *view in views)
{
if([view isKindOfClass:[UITableViewCell class]])
{
cell = (ProductMerchantCell*)view;
//cell.img=#"date.png";
}
}
}
cell.selectionStyle=UITableViewCellSelectionStyleNone;
txtfield = [[UITextField alloc]initWithFrame:CGRectMake(104, 36, 58, 31)];
txtfield.textColor = [UIColor colorWithRed:56.0f/255.0f green:84.0f/255.0f blue:135.0f/255.0f alpha:1.0f];
txtfield.delegate = self;
txtfield.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
txtfield.returnKeyType = UIReturnKeyDone;
indexVal = indexPath.row;
[txtfield setBorderStyle:UITextBorderStyleRoundedRect];
txtfield.textAlignment = UITextAlignmentCenter;
txtfield.text = [quantity_array objectAtIndex:indexPath.row];
// NSLog(#" txtfield.text %#", txtfield.text);
[txtfield setTag:indexPath.row];
[txtfield setAutocapitalizationType:UITextAutocapitalizationTypeWords];
NSString *total_str_price1=[[mainDetaileArray objectAtIndex:indexPath.row]valueForKey:#"total_product_price"];
cell.availbl_pro_lbl.text=[NSString stringWithFormat:#"Total : %#%#",add_currnce_str,total_str_price1];
cell.title_pro_lbl.text=[[mainDetaileArray objectAtIndex:indexPath.row]valueForKey:#"product_title"];
str_price=[[mainDetaileArray objectAtIndex:indexPath.row]valueForKey:#"product_price"];
cell.price_Pro_lbl.text=[NSString stringWithFormat:#"Price : %#%#",add_currnce_str,str_price];
[cell.contentView addSubview:txtfield];
return cell;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
addtoValue = textField.text;
[quantity_array replaceObjectAtIndex:textField.tag withObject:textField.text];
// NSLog(#"quantity_array %#",quantity_array);
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
[cell.Quantity_txt resignFirstResponder];
return YES;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[cell.Quantity_txt resignFirstResponder];
}

Detecting Reachability

I have Reachability class that I adopted from Apple. My problem is implementing my reachability detection in my ListViewController rather than in the ReachabilityAppDelegate shown in Apple. My problems:
I want to link the calling method in the (UITableViewCell *)tableView:(UITableView
*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath and the reachability detection
I am trying to disable my cell if they detect it is not connected and enable the cell if it
is connected
This is coded in viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver: self selector:#selector(reachabilityChanged:) name:kReachabilityChangedNotification object: nil];
The reachabilityChanged as below:
-(void) reachabilityChanged: (NSNotification* )note{
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass:[Reachability class]]);
[self updateInterfaceWithReachability: curReach];
}
How do I implement my disabling of UITableViewCells in
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Take note that I have coded this in the above method:
NSInteger row = [indexPath row];
NSString *contentForThisRow = nil;
static NSString *MyIdentifier = #"MyIdentifier";
if (tableView == [[self searchDisplayController] searchResultsTableView]) {
// Sort search results in alphabetical order
NSArray *sorted = [searchResults sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
contentForThisRow = [sorted objectAtIndex:row];
}else {
contentForThisRow = [nameArray objectAtIndex:row];
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier]autorelease];
}
// Set Device names into Cells
cell.textLabel.text = contentForThisRow;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
NSLog(#"Load cell done");
}
you can code like this , add an instance var BOOL _isOffline
in the class and in your updateInterfaceWithReachability: method
- (void)updateInterfaceWithReachability:(Reachability* )curReach
{
if(curReach == XXXXNotReachable)
{
//your code
_isOffline = YES;
}
else
{
_isOffline = NO;
}
[_tableView reloadData];
}
in your -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
you should add your code to deal with the cell , may be
if(_isOffline)
{
cell.userInteractionEnabled = NO;
}
else
{
cell.userInteractionEnabled = YES;
}

How UITableView show two different arrays one at a time?

The below Code works but not as i wish.i want that when i click UIbutton its automaically update the new value in UITableview instead of old value.Below Code works only when i press the UIbuttons and after that when i scroll the UITableview then it update the UItableview with new values.
In my application i using UITableview as Subclass of my mainclass.as image show below
I add Tableview in my Mainclass which is "testingViewController" like this way
In testingViewController.h
#import "Inputtableview.h"
#interface testingViewController :UIViewController<UITableViewDelegate,UITableViewDataSource> {
Inputtableview *inputview;
IBOutlet UITableView *inputtbl;
}
#end
In testingViewController.m
- (void)viewDidLoad {
btn1bool=FALSE;
if (inputview == nil) {
inputview = [[Inputtableview alloc] init];
}
[inputtbl setDataSource:inputview];
[inputtbl setDelegate:inputview];
inputview.view = inputview.tableView;
}
Now in Button action method
-(IBAction)input:(id)sender
{
btn1bool=TRUE;
}
my Subclass code "inputtableview.m" is show below
- (void)viewDidLoad {
[super viewDidLoad];
listOfItems=[[NSMutableArray alloc] initWithObjects:#"Iceland",#"Greenland",#"Switzerland",
#"Norway",#"New Zealand",#"Greece",#"Italy",#"Ireland",nil];
array1 = [[NSMutableArray alloc] initWithObjects:#"A",#"B",#"C",#"D",#"E",#"F",#"G",#"H", nil] ;
}
#pragma mark -
#pragma mark Table View datasource methods
-(NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
if (btn1bool) {
return [array1 count];
}
else {
return [listOfItems count];
}
[self.tableView reloadData];
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
NSLog(#"Row: %i", indexPath.row);
if (btn1bool) {
NSString *cellValue = [array1 objectAtIndex:indexPath.row];
cell.text = cellValue;
}
else {
NSString *cellValue = [listOfItems objectAtIndex:indexPath.row];
cell.text = cellValue;
}
return cell;
}
Any help will be appriated.
Just put the following code:
[inputtbl reloadData];
There are a few things you need to change in your project, but I assume this project is just for testing stuff.
You want the date to reload after you pressed the button, so you call the method in the IBAction.
-(IBAction)input:(id)sender
{
btn1bool=TRUE;
[inputview.tableView reloadData];
}
To switch between the 2 data sources when the button is pressed you can change to this line of code: btn1bool=!btn1bool;
(NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
if (btn1bool) {
return [array1 count];
} else {
return [listOfItems count];
}
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath is correct

Searching a TableView of annotations

I had no idea how to set up a database when i started so i have 80 annotations that all look like this
workingCoordinate.latitude = 50.795825;
workingCoordinate.longitude = -1.103139;
MainViewAnnotation *Levant = [[MainViewAnnotation alloc] initWithCoordinate:workingCoordinate];
[Levant setTitle:#"Levant"];
[Levant setSubtitle:#"Unit R09, Gunwharf Quays"];
[Levant setAnnotationType:MainViewAnnotationTypePortsmouth];
[mapView addAnnotation:Levant];
They are grouped into 22 cities through the MainViewAnnotationType, which is coded as follows:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 21;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if(section == MainViewAnnotationTypeBirmingham)
{
return #"Birmingham";
}
else if(section == MainViewAnnotationTypePortsmouth)
{
return #"Portsmouth";
}
return nil;
}
The annotations are then put into a TableView like so;
- (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] autorelease];
}
NSMutableArray *annotations = [[NSMutableArray alloc] init];
if(indexPath.section == 0)
{
for(MainViewAnnotation *annotation in [mapView annotations])
{
if(![annotation isKindOfClass:[MKUserLocation class]])
{
if([annotation annotationType] == MainViewAnnotationTypeBirmingham)
{
[annotations addObject:annotation];
}
}
}
cell.textLabel.text = [[annotations objectAtIndex:indexPath.row] title];
}
...
else if(indexPath.section == 17)
{
for(MainViewAnnotation *annotation in [mapView annotations])
{
if(![annotation isKindOfClass:[MKUserLocation class]])
{
if([annotation annotationType] == MainViewAnnotationTypePortsmouth)
{
[annotations addObject:annotation];
}
}
}
cell.textLabel.text = [[annotations objectAtIndex:indexPath.row] title];
}
return cell;
}
and then when a cell is clicked, will zoom in on the annotation.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
for(MainViewAnnotation *annotation in [mapView annotations])
{
if([[[[tableView cellForRowAtIndexPath:indexPath] textLabel] text] isEqualToString:[annotation title]])
{
[mapView setRegion:MKCoordinateRegionMake([annotation coordinate], MKCoordinateSpanMake(.003, .003)) animated:YES];
}
}
}
My question is, I would like to be able to search my annotations either through their city their in or by their annotation name. I have a search bar controller already in my interface and it has been connected to my tableview, just not written any code.
I would like the search to be hidden unless i click a search button then hide when i click on a cell.
New to Xcode, any help including some code examples would be much appreciated.
What I did is to create my UITableView not programmatically but using Interface Builder. Create your own custom ViewController and add inside an UITableView. Don't forget to set (by interface builder) delegate and datasource. Afterwards I think it might be easier for you to manage your hidden/show search bar.
Hope this can help.

UITableViewCell reloadcellsAtIndexPaths increases the height of the following cell but not the actual one

[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
after this I am increasing the height of the 1st cell in heightforRowAtIndexPath. But to my surprise it is increasing the height of the second cell, but when I scroll the table view... the height of the first one is set back to desired.
If I reload the entire table using [tv reloaddata] it works fine.. does not work only if i do the particular cell
Any help on this would be helpful..
As written in the comments above, I only have a vague understanding about what you want to achieve. I assume you want to extend cell by changing their height. You just mention the first cell, but I guess, you want to be able, to do it for any cell when being clicked.
The complete project is available at github
.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
NSIndexPath *selectedIndexPath;
NSDictionary *articles;
}
#end
.m
#import "FirstViewController.h"
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
selectedIndexPath = nil;
articles = [[NSDictionary dictionaryWithObject:[NSArray arrayWithObjects:#"one", #"two", #"three",
#"four", #"five", #"six",
#"seven", #"eight", #"nine",
#"ten", #"eleven", nil]
forKey:#"title"] retain];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
[selectedIndexPath release];
[articles release];
[super dealloc];
}
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[articles allKeys] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [[articles allKeys] objectAtIndex : section];
}
- (int)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
id key = [[articles allKeys] objectAtIndex:section];
return [[articles objectForKey : key] count];
}
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ((selectedIndexPath != nil) && (selectedIndexPath.row == indexPath.row))
return 80.0;
return 40.0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * MyIdentifier = #"MyIdentifier";
UITableViewCell * cell = [self.tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}
id key = [[articles allKeys] objectAtIndex:indexPath.section];
cell.textLabel.text = [[articles objectForKey:key] objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (selectedIndexPath == indexPath) {
selectedIndexPath = nil;
} else {
selectedIndexPath = indexPath;
}
[self.tableView deselectRowAtIndexPath : indexPath animated : NO];
[tableView beginUpdates];
[tableView endUpdates];
}
#end
This code is quite rough, as I just extracted it from a project in my very early iPhone-days. i.e. properties are missing.