Objective C: UITable Method "didSelectRowAtIndexPath" does not work if label is added to cell - objective-c

In my implementation, I had to add a custom label to the cell. However, I realize that by doing so, the cell area that is covered by the custom label will not react to the user's 'click' and hence will not trigger the method "didSelectRowAtIndexPath".
CustomOHAttributLabel *questionLabel = [[CustomOHAttributLabel alloc]initWithFrame:CGRectMake(10, (60-labelHeight)/2, 280, labelHeight)];
[cell.contentView addSubview:questionLabel];
Is there a way to allow the whole cell area to be responsive to the user's touch even after adding a Custom label to it?

Make a custom button and put that over the lavel and onClick call the same code, see this
CustomOHAttributLabel *questionLabel = [[CustomOHAttributLabel alloc]initWithFrame:CGRectMake(10, (60-labelHeight)/2, 280, labelHeight)];
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
btn.frame=CGRectMake(10, (60-labelHeight)/2, 280, labelHeight);
[btn addTarget:self action:#selector(doSomeThing) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:questionLabel];
[cell.contentView addSubview:btn];
-(void)doSomeThing
{
//write code which you write in didSelectRowAtIndexPath method
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self doSomeThing];
}

Related

Objective C > UITableViewCell button not depressing

I have the following button being created in the cellForRowAtIndexPath section for this tableView:
UIButton *sched_button_a1 = [UIButton buttonWithType:UIButtonTypeCustom];
sched_button_a1.frame = CGRectMake(0, 0, 110, 52);
CGRect frame_a1 = sched_button_a1.frame;
// Resize height based on length of appointment
frame_a1.size.height = heightCalc;
sched_button_a1.frame = frame_a1;
[sched_button_a1 addTarget:self action:#selector(showAppointment:) forControlEvents:UIControlEventTouchUpInside];
[sched_button_a1 setTitle:[NSString stringWithFormat:#"APPT: %#", APPT_ID ] forState:UIControlStateNormal];
sched_button_a1.layer.backgroundColor = [UIColor redColor].CGColor;
[sched_a1 addSubview:sched_button_a1];
As you can see it's calling showAppointment which is presently just:
-(void)showAppointment:(UIButton*)sender {
NSLog(#"Button pushed");
}
showAppointment is also defined here:
-(void)showAppointment:(UIButton*)sender;
The button shows up fine and gets the correct text and background and appears to be in the foreground, however, when I click on it nothing happens and it doesn't look like the button even gets depressed.
What am I doing wrong or missing?
Edit: I have gone back and removed the sched_a1 view so that the button is directly created in the contentView and this had no effect. It still appears that the only gesture being recognized is the one used to scroll the table. Tapping the button does not appear to change the color of the text or otherwise indicate that the button has been pressed and no log entry is created.
Edit 2: Added cellForRowAtIndexPath to paste bin
http://pastebin.com/WXezfW96
I had a similar issue recently, which I struggled to understand. The solution I came up with was to set the bounds of the button as well and also check for UIControlEventTouchDown rather than UIControlEventTouchUpInside.
Have you tried using cancelsTouchesInView? If you added tap gesture, I think the tap gesture or the tap in table cell overrides the touches in your button. Try using this code:
UIGestureRecognizer *tap= [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(yourAction)];
tap.cancelsTouchesInView = NO;
tap.delegate = self;
[yourButton addGestureRecognizer:tap];
But don't forget to add <UIGestureRecognizerDelegate> in your .h file
But I agree on Mike. Make it short and simple when creating table cell. I think you can use custom cell subclass and xib file.
I'm also new to objective C so if I say something wrong I'm sorry, I'm just trying to help.
UIButton *sched_button_a1 = [UIButton buttonWithType:UIButtonTypeCustom];
in this change UIButtonTypeCustom to UIButtonTypeRoundedRect
Scott, you may want to try my famous troubleshooting technique:
Determine whether the button or the action is the root cause:
UIImage *image = [UIImage imageNamed:#"image.png"];
[button setBackgroundImage:image forState:UIControlStateHighlighted|UIControlStateSelected]
Instead of:
-(void)showAppointment:(UIButton*)sender {
try
-(void)showAppointment:(id*)sender {
Use breakpoints.
If none of the above works consider refactoring your code that looks a bit messy.
Hey i have checked the code you wrote, it is working fine. Can you check if you have written similar to the code below in your cellForRowAtIndexPath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *Identifier = #"Identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:Identifier];
}
UIButton *sched_button_a1 = [UIButton buttonWithType:UIButtonTypeCustom];
sched_button_a1.frame = CGRectMake(0, 0, 110, 52);
CGRect frame_a1 = sched_button_a1.frame;
[sched_button_a1 addTarget:self action:#selector(showAppointment:) forControlEvents:UIControlEventTouchUpInside];
[sched_button_a1 setTitle:#"Your Text" forState:UIControlStateNormal];
sched_button_a1.layer.backgroundColor = [UIColor redColor].CGColor;
[cell.contentView addSubview:sched_button_a1];
return cell;
}
I was not able to debug further as you have not kept your entire cellForRowAtIndexPath code. Hope this could help you to solve your problem
Since you are using a button type of UIButtonTypeCustom, you will need to set the attributes for UIControlStateHighlighted and UIControlStateSelected so that you achieve the effect you want for appearing to press the button.
You can change the title color or the background image for the highlighted and selected states using one of the following UIButton methods:
- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state
As an additional note regarding the code in the cellForRowAtIndexPath, you shouldn't be getting the data from sql in the method it would be destructive to your table view performance, get all the data you need before and have them stored in object in an array and then in the cellForRowAtIndexPath method you would just update the values labels from the object for the row.

refresh the uitableview contents

I have added uitableview in which I am trying to add custom UIButton. It is added successfully with this code:
image=[UIButton buttonWithType:UIButtonTypeCustom];
image.frame=CGRectMake(240, 7, 25, 25);
image.tag=101;
image2=[UIButton buttonWithType:UIButtonTypeCustom];
image2.frame=CGRectMake(240, 7, 25, 25);
image2.tag=102;
if ([outputlabel.text isEqualToString:#"Yes"]||[outputlabel.text isEqualToString:#"Yes"]) {
[image setImage:[UIImage imageNamed:#"tick.png"] forState:UIControlStateNormal];
[cell1.contentView addSubview:image];
[cell1.contentView bringSubviewToFront:image];
}
else
{
[image2 setImage:[UIImage imageNamed:#"cross.png"] forState:UIControlStateNormal];
[cell1.contentView addSubview:image2];
[cell1.contentView bringSubviewToFront:image2];
}
Its working fine at first. When table view reload it overlaps the uibutton old image. I am unable to refresh the whole table with new values. Someone has an idea what I am doing wrong in code.
Updated. Always Create content view for cell in cell == nil block. Use that contentview outside by the tag.. Then only it wont overlap and reuse ur cell perfectly..
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIndentifier];
//Add your button here.. set the tag.
UIButton image=[UIButton buttonWithType:UIButtonTypeCustom];
image.frame=CGRectMake(240, 7, 25, 25);
image.tag=101;
}
UIButton *btn = (UIButton *)[cell.contentView viewWithTag:101];
if ([outputlabel.text isEqualToString:#"Yes"]||[outputlabel.text isEqualToString:#"Yes"])
{
[btn setImage:[UIImage imageNamed:#"tick.png"] forState:UIControlStateNormal];
}
else
{
[btn setImage:[UIImage imageNamed:#"cross.png"] forState:UIControlStateNormal];
}
Just do like this in cellForRowAtIndexPath.. It will helpful for you..
Basically, if we want to refersh the contents of tableview then need to use this reloadData. Did you try :-
[yourTableView reloadData];
Make sure you implement -cellForRowAtIndexPath:. Then refresh your tableViewCells by calling reloadRowsAtIndexPaths:withRowAnimation: on the tableView in question.
The tableView will in turn call cellForRowAtIndexPath, and you simply return the configured cells there.
If you have static cells, you can simply access whatever you need to change by hooking the controls up to an IBOutlet.
Try refreshing your cell's view using
[cell1.contentView setNeedsDisplay:TRUE];
every time you set the image.
I am suspecting, that you adding this images in -tableView:cellForRawAtIndexPath: method.
First of all - if you reusing cell with some reuse identifier, the Cell will stay in memory and will reused when it needed. It's means that all subviews of your cell will be retained. In this case you need to prepare cell for reusing every time. For example - remove all subViews of cell.
But better way, I recommend in case of less number of operations - to create subclass of UITableViewCell and add UIButton as a property of that cell.
Then you will only need to change this property depend of your condition.
if ([outputlabel.text isEqualToString:#"Yes"]) {
[cell1.button setImage:[UIImage imageNamed:#"tick.png"] forState:UIControlStateNormal];
}
else
{
[cell1.image setImage:[UIImage imageNamed:#"cross.png"] forState:UIControlStateNormal];
}
Of course, you button must be added in cell.contentView in the Cell initialiser. Usually it is method -initWithStyle:reuseIdentifier: of your custom cell .m file.

one button in each section of uiTableView objective-C

I have a uitableview and in my table I have different section and in each section different rows,I want to add one button in last row of each sections
I used sectionFooter, and here is my code, but I don't know why I have it just in my last section of table and also it's not appear with scroll.
Here is my code:
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 50;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
if(footerView == nil) {
footerView = [[UIView alloc] init];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// [button setBackgroundImage:image forState:UIControlStateNormal];
//the button should be as big as a table view cell
[button setFrame:CGRectMake(10, 3, 300, 44)];
//set title, font size and font color
[button setTitle:#"Report New Time" forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont boldSystemFontOfSize:20]];
[button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
//set action of the button
[button addTarget:self action:#selector(removeAction:)
forControlEvents:UIControlEventTouchUpInside];
//add the button to the view
[footerView addSubview:button];
}
//return the view for the footer
return footerView;
}
what is wrong here, Would you please help me!
Thanks in advance!
You need to remove the if statement in your tableView:viewForFooterInSection: method. That's causing only one view to be created.
One UIView has to have only one superview. You have to create footerView for every section.
You are reusing the footerView for every section, partly by just keeping one footerView instance variable, partly by just creating it once. Every time UITableView asks you for a footer view for a section and it gets back the same view, that view is moved since it can't stay in all those places at the same time. The solution is to not use a single view.
Use an NSMutableDictionary to hold NSNumbers with the section number as key and the appropriate footer view as the value. Change the code to work with the section's "slot" in the dictionary instead of a single instance variable.

add an action on a button without ibaction

I'm working on a mapkit view, i added a button on an annotation like this:
UIButton *bt = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[bt setFrame:CGRectMake(0, 0, 30, 30)];
annView.rightCalloutAccessoryView = bt;
i want to go to another view (for example expleViewController) when touching that button, i'm accustomed to do it using an IBAction method and link it with the button using Interface Builder, but this button is created manually, so how can I link it?
[bt addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
- (void)buttonPressed:(UIButton *)b
{
// do whatever you want ;)
}

How to change the image of the button on click of the button in objective c

I have placed a pause button in UI, where when the user clicks the button, the image of button from pause image it has to change to the start image. I have placed both the start and the pause images in the bundle, I am able to do this,but when i click on start again , it should show pause image button,How to do this, the following is the code i am using,
-(IBAction)btnClked:(id)sender
{
[pauseButton setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
UIButton *btn=(UIButton *)sender;
[btn setImage:[UIImage imageNamed:#"start.png"] forState:UIControlStateNormal];
}
You need a variable to keep track of that state change. A BOOL is fine.
But using your code, you can "abuse" the tag property of UIButton to tell if it's playing (tag == 1) or paused (tag == 0)
-(IBAction)btnClked:(id)sender {
UIButton *btn=(UIButton *)sender;
if (btn.tag == 1) {
btn.tag = 0;
[btn setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
} else {
btn.tag = 1;
[btn setImage:[UIImage imageNamed:#"start.png"] forState:UIControlStateNormal];
}
}
You can use UIButton's selected state to do the same. For example, while initiating the button you have to define 2 images. One for normal state and other for selected state. When touch event of the button fired, you have to make it selected. If it is already selected you need to deselect it. This is much better, than maintaining additional variables to check selected state of the button. Also you could improve the performance with this approach.
Code example
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIButton *startButton = [[UIButton alloc] initWithFrame:CGRectMake(200, 300, 60, 60)];
[startButton setBackgroundImage:[UIImage imageNamed:#"start.png"] forState:UIControlStateNormal];
[startButton setBackgroundImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateSelected];
[startButton addTarget:self action:#selector(modeButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:startButton];
}
- (IBAction)modeButtonClick:(id)sender {
UIButton *startButton = (UIButton *)sender;
[startButton setSelected:![startButton isSelected]];
}
If you are creating the button from story board or XIBs set the backgroud image for default state config and selected state config.