I've got a tableview containing array of names. The search bar works perfectly filtering the names in the table view.
The problem is the didSelectRowAtIndexpath is not getting fired when clicking the search tableview cell. Could you help me out?
What is the thing that I'm missing? Should I include any special delegate to involve search tableview cell click.
Below is the image and code.
-(void)search
{
nameArray = [[NSMutableArray alloc] init];
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 160, 44)];
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
self.tableViewFriendsList.tableHeaderView = searchBar;
}
- (void)searchDisplayController:(UISearchDisplayController *)controller
willShowSearchResultsTableView:(UITableView *)tableView
{
[tableView setRowHeight:70];
[tableView reloadData];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.tableViewFriendsList) {
NSString *friendsID =[[[self.friendsDictionary objectForKey:#"data"] objectAtIndex:indexPath.row] objectForKey:#"id"];
[[FacebookHelper sharedFacebookHelper] postOnWallWithDelegate:self andID:friendsID];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
NSLog(#"I ve come here");
NSString *friendsID =[friendsListIdArray objectAtIndex:indexPath.row];
[[FacebookHelper sharedFacebookHelper] postOnWallWithDelegate:self andID:friendsID];
}
}
You forgot to set
searchController.searchResultsDelegate = self;
I do something in one of my projects that may be of assistance:
// add gesture to detect when table view is being tapped so that keyboard may be dismissed
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(dismissKeyboard)];
gestureRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:gestureRecognizer];
Moreover I am wondering why you have a search bar within a table cell. Would you mind posting a screen shot of it in your app? I am afraid you may be doing more work than is necessary.
Related
I have gesture recognisers set up on my table view.
Swipe to the right and the accessory changes to an image of a tick
Swipe to the left and is changes to a chevron image
If a cell is tapped, it loads a local HTML file.
If you swipe to the right, the tick appears as it should. However, if you then tap a cell to view a HTML file and come back to the table view, the image reverts to the chevron.
What's the best way to ensure the tick stays as it should?
EDIT
Further code:
From 'viewDidLoad':
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSwipeRight:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self.tableView addGestureRecognizer:recognizer];
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSwipeLeft:)];
//recognizer.delegate = self;
[recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[self.tableView addGestureRecognizer:recognizer];
- (void)handleSwipeLeft:(UISwipeGestureRecognizer *)gestureRecognizer
{
//Get location of the swipe
CGPoint location = [gestureRecognizer locationInView:self.tableView];
//Get the corresponding index path within the table view
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
//Check if index path is valid
if(indexPath)
{
//Get the cell out of the table view
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
//Update the cell or model
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"disclosure.png"]];
}
}
- (void)handleSwipeRight:(UISwipeGestureRecognizer *)gestureRecognizer
{
CGPoint location = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
if(indexPath)
{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
// cell.accessoryType = UITableViewCellAccessoryCheckmark;
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tick.png"]];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"MFGCell";
MFGCell *cell = (MFGCell *) [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MFGCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.itemTitle.text = [item objectAtIndex:indexPath.row];
cell.itemDescription.text = [description objectAtIndex:indexPath.row];
cell.itemImageView.image = [UIImage imageNamed:[icons objectAtIndex:indexPath.row]];
return cell;
}
In reaction to the user's swipe you should store the user's choice (e.g. in a private instance variable of type NSMutableArray). When the user comes back to the table view you can then reuse the information in your tableView:cellForRowAtIndexPath: to setup the cell with the correct accessory style.
Property declaration:
#property(nonatomic, retain) NSMutableArray* _accessoryStyle;
Synthesize the property. Then add this snippet to the bottom of handleSwipeLeft: to store the user's choice:
- (void)handleSwipeLeft:(UISwipeGestureRecognizer *)gestureRecognizer
{
[...]
NSNumber* number = [numberWithInt:0];
[_accessoryStyle replaceObjectAtIndex:indexPath.row withObject:number];
}
Add a similar snippet to the bottom of handleSwipeRight::
- (void)handleSwipeRight:(UISwipeGestureRecognizer *)gestureRecognizer
{
[...]
NSNumber* number = [numberWithInt:1];
[_accessoryStyle replaceObjectAtIndex:indexPath.row withObject:number];
}
In tableView:cellForRowAtIndexPath::
NSString* accessoryImageName;
NSNumber* number = [_accessoryStyle objectAtIndex:indexPath.row];
switch ([number intValue])
{
case 0:
accessoryImageName = #"disclosure.png";
break;
case 1:
accessoryImageName = #"tick.png";
break;
default:
// replace with your error handling code
return nil;
}
cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:accessoryImageName]];
For all this to work you need to initialize the _accessoryStyle array with the same number of elements that you expect your table view to have cells. For instance, in your view controller's viewDidLoad:
- (void) viewDidLoad
{
[super viewDidLoad];
self._accessoryStyle = [NSMutableArray arrayWithCapacity:0];
NSNumber* defaultAccessoryStyle = [numberWithInt:0];
int numberOfRows = 17; // get the real number from somewhere
for (int index = 0; index < numberOfCells; ++index)
[_accessoryStyle addObject:defaultAccessoryStyle];
}
And to balance this you need to add
- (void) viewDidUnload
{
[super viewDidUnload];
self._accessoryStyle = nil;
}
There is still much room for improvement:
Find better variable names
Use an enumeration for the different styles instead of just hardcoded numbers 0 and 1
Do not allocate a new UIImageView for each table view cell, just allocate two of them and use the right one depending on the accessory style
For your problem, there is an underlying logic issue because there is either a swipe left event firing when it should not or the views are just being unloaded and resetting to default. See if you can log when the events fire; otherwise the state of the view should be preserved. Also what I would do is add an extra state variable like int currentCellState that you change when you enter your different states to keep track of your states. Then in your viewDIdLoad make sure that all your data and your view are in sync, ie the value of currentCellState matches the state of your view.
The best way to do this is to put the images/buttons you have in an array, and each time the view loads it shows the item which index is selected..
in order to do this, the swipeMethode should be modified to something like this
-(void)swipeMethod: (UISwipeGestureRecognizer *) sender
{
if(sender.direction ==
UISwipeGestureRecognizerDirectionLeft && index < [myArray count]){
[self setSelectedIndex:index+1 animated:YES];
index++;
}else if (sender.direction == UISwipeGestureRecognizerDirectionRight && index > 0) {
[self setSelectedIndex:index-1 animated:YES];
index--;
}else {
return;
}
}
in the viewDidLoad add this code:
leftRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeMethod:)];
[leftRecognizer setDirection: UISwipeGestureRecognizerDirectionLeft];
[self.tableView addGestureRecognizer:leftRecognizer];
rightRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeMethod:)];
[rightRecognizer setDirection: UISwipeGestureRecognizerDirectionRight];
[self.tableView addGestureRecognizer:rightRecognizer];
i'm developing a bluetooth apps.1) I want to hide a tableview when i start the apps..after i pressed a action button i want to enable a tableview.. 2)if i again press a action button means tableviewcell clear the data and show empty before searching..give me an idea..
some of the code-
- (IBAction)connectButtonTouched:(id)sender
{
[self.deviceTable reloadData];
self.connectButton.enabled = YES;
[self.deviceTable reloadData];
peripheralManager = [[PeripheralManager alloc] init];
peripheralManager.delegate = self;
[peripheralManager scanForPeripheralsAndConnect];
[self.deviceTable reloadData];
[NSTimer scheduledTimerWithTimeInterval:(float)5.0 target:self selector:#selector (connectionTimer:) userInfo:nil repeats:YES];
alert=[[UIAlertView alloc] initWithTitle:#"Bluetooth" message:#"Scanning" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
UIActivityIndicatorView *progress=[[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(125, 50, 30, 30)];
[alert addSubview:progress];
[progress startAnimating];
[alert show];
}
tableview
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [device 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=[device objectAtIndex:indexPath.row];
cell.accessoryType=UITableViewCellAccessoryDetailDisclosureButton;
return cell;
}
TableView Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[tableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"TableDetails" sender:tableView];
}
1.If you want to hide table View before clicking a button you can use
tableView.hidden=YES;
and inside
- (IBAction)connectButtonTouched:(id)sender, you can make it visible by using
tableView.hidden=NO;
[tableView reloadData]
OR
2.If you are developing app for iPad, then you can use UIPopOverController to show the data. You can load the tableView inside UIPopOverController when button is clicked.
Add BOOL flag in .h file
Now in ViewDidLoad add this:
flag = FALSE;
in tableview delegate method
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(flag)
return [device count];
else
return 0;
}
In your button action method:
- (IBAction)connectButtonTouched:(id)sender
{
if(!flag)
flag = TRUE;
else
flag = FALSE;
[self.deviceTable reloadData];
//your other code here
}
if they are in the same view, why not give the tableView a alpha of 0 and userInteractionEnabled = NO ?
Although, I think it would be easier if, instead of linking your tableView from interface builder, keep it as a member and initialize/reinitialize it when you tap your button.
something like:
`- (IBAction)connectButtonTouched:(id)sender {
if (self.deviceTable) {
[self.deviceTable removefromSuperview];
self.deviceTable = nil;
}
self.deviceTable = [[UITableView alloc] init];
// and so on
`
Also you might put another method in peripheralManager delegate ... something like
-(void)didFinishScanning and inside redraw your table view.
I hope I understood the question well, and helped you in any way
I have a UITableView loading some tweets, all works nicely but when I populate the table it doesn't enter to the CellForRow method til I touch the table view.... does somebody know how to solve this?
tab = [[UITableView alloc] initWithFrame:CGRectMake(10, 300, 400, 200) style:UITableViewStylePlain];
tab.dataSource = self;
tab.delegate = self;
then...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"entra a cellula");
Tweet *t = [tweets objectAtIndex:indexPath.row];
static NSString *MyIdentifier = #"MyIdentifier";
// Try to retrieve from the table view a now-unused cell with the given identifier.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
// If no cell is available, create a new one using the given identifier.
if (cell == nil) {
// Use the default cell style.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:MyIdentifier];
}
cell.textLabel.text = t.screenName;
cell.detailTextLabel.text = t.text;
cell.imageView.image = t.profileImage;
return cell;
}
Best guess based on what we know is that you aren't adding the table as a subview on the main thread. This means that redrawing doesn't occur until you scroll. Try wrapping the addsubview call in a GCD call like so:
dispatch_async(dispatch_get_main_queue(), ^() {
[self addSubview:tab];
});
When you finished loading your tweets call this method:
[tab reloadData];
to reload your tableView data source.
I have a uitableView with different sections and rows that I created them programmatically
when I cleck on one row I will go to the new views and in new views in navigation bar I have canel button
with cancel button it should work like a back button but when I click on cancel it load the table but change the table style from group to plain
Thanks in Advance!
does any one know why?
would you please help me
I want to know why it changes.
what should I add to have the same stype
here is my code:
in first table, I added the style both programmatically and via storyboard
- (id)initWithStyle:(UITableViewStyle)style
{
style = UITableViewStyleGrouped;
self = [super init];
if (self) {
self = [super initWithStyle:style];
monthTitle = [[NSMutableArray alloc] init];
}
return self;
}
button code
-(void)cancelItem{
Report *report = [[Report alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:report animated:YES];
[self.tableView reloadData];
}
Edit
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_selectedIndex = indexPath.section;
[self.tableView reloadData];
switch (indexPath.section){
case 0:
[self performSegueWithIdentifier:#"WorkTime" sender:self];
We can set the style as
[[UITableViewController alloc] initWithStyle:UITableViewStyleGrouped];
I'm having a problem with my current App. It has one UITableView in the UIViewController. I have one UIButton at the bottom (out of the UITableView). It works in that way:
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"bla"]) {
[[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:#"bla"];
[tableView reloadData];
} else {
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"tasks2do"];
[tableView reloadData]; }
This worked when I had the cell.textLabel.text Method in this way:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *ident = #"indet";
cell = [tableView dequeueReusableCellWithIdentifier:ident];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:ident] autorelease];
}
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"bla"]) {
cell.textLabel.text = [firstArray objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [secondArray objectAtIndex:indexPath.row];
}
return cell; }
Now I want to use an UILabel instead of cell.textLabel, because I need it for some reasons (eg. setting the labels frame)
For that I used the following code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *ident = #"indet";
cell = [tableView dequeueReusableCellWithIdentifier:ident];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:ident] autorelease];
}
UILabel *thislabel = [[[UILabel alloc] initWithFrame:CGRectMake(10, 10, 250, 44)] autorelease];
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"bla"]) {
[thislabel setText:[firstArray objectAtIndex:indexPath.row]];
} else {
[thislabel setText:[secondArray objectAtIndex:indexPath.row]];
}
[cell.contentView addSubview:thislabel];
return cell; }
That works fine, until I push the UIButton for switching. It switches, the cell shows the new text but behind the new text is still the old text as you can see here:
http://d.pr/Rqx2
(the firstArray contains the letter L, the secondArray contains the Letter J, it mixes up both up)
Do you have any idea for solving this problem since I tried some stuff (for example using 2 UILabels for the arrays and hide one)? Would be cool. :)
I hope my English is not too bad to understand, my English skills for writing aren't the best, I'm sorry for that.
If you need further information / code just post it, shouldn't be a problem.
I recommend you create a UITableViewCell subclass in which you configure the label (set frame and add it as subview in UITableViewCell's initializer). Add a property for setting the text in the label and write a setter like this for the property:
- (void)setLabelText:(NSString *)newLabelText
{
if ([self.labelText isEqualToString:newLabelText]) return;
[labelText autorelease];
labelText = [newLabelText copy];
self.label.text = labelText;
[self.label setNeedsDisplay]; // or perhaps [self setNeedsDisplay];
}
Edit: by the way, the issue you're dealing with is the caching. You recreate a new label every time a cell comes in view, even if the cell already had a label before. This happens because you initialize an UILabel outside the UITableViewCell initializer (which only should be called once for every cached cell, afterwards it can be retrieved from cache, including all it's subviews).