I have simply dragged a custom style button to a cell in storyboards. The problem is that when I press the button, it clicks the cell and not the button.
What could cause this?
Do I need to increase the click area? If so how?
Do I need to bring the button to the front? If so how?
Thanks!
My cell for row at index path looks like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
MainUserViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell initWithStyle:nil reuseIdentifier:nil];
[cell.descrlptionLabel sizeToFit];
[cell.userNameButton addTarget:self action:#selector(userNameClicked:) forControlEvents:UIControlEventTouchDown];
return cell;
}
No need for the initWithStyle line in your method. You should eliminate it.
[cell initWithStyle:nil reuseIdentifier:nil];
The cell is dequeued and should already be ready and initialized. You are working with storyboard, obviously, so the dequeue method is guaranteed to return a valid cell, auto-creating it if necessary.
This is most likely messing things up.
Some more things to check: Make sure the button is topmost in your story board file (i.e. the bottom item in the list on the left). Your resizing of the label could cover it otherwise. Also, make sure you did not accidentally set userInteractionEnabled to NO.
Related
I used this code in cellForRowAtIndexPath method. When I click on button or scroll table this button is shown two times. Why is this button shown 2 times please help me?
UIButton *trashbtn=[[UIButton alloc]initWithFrame:CGRectMake(cell.frame.size.width-20, cell.frame.size.height-30, 20, 20)];
[trashbtn setImage:[UIImage imageNamed:#"editor_trash"] forState:UIControlStateNormal];
[trashbtn addTarget:self action:#selector(DeleteMyAssociate:) forControlEvents:UIControlEventTouchUpInside];
[trashbtn setTag:indexPath.row];
[cell addSubview:trashbtn];
You should firstly add a UITableViewCell within your table in IB. Then give an identifier e.g. "MyCellIdentifier" to that cell. Still on IB, add your outlets, to that cell e.g. the button, the textFields... You can initially set the button to be invisible. Then in the method cellForRowAtIndexPath, you do:
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCellIdentifier"];
if(cell){
myButton.hidden = NO; //
myTextField.text = #"BlaBlaBla";
}
}
Hey I can give you a suggestion that use auto layout and storyboard to add button rather than adding it programmatically. That is more better and cleaner approach.
The problem you are facing is that cells are reused in tableviews, So the first time you create a button and add it to the cell, it appears once. But if it is dequeued, it already has the button, so when you add another one you end up with multiple buttons.
There are two ways to correct this.
Firstly, remove the button in the cell's prepareForReuse method, which is called just after the cell is reused.
Secondly, avoid creating custom views in the cellForTableView... method. Use a custom cell that already has the button. Now, you may ask, how do I hook up the action for the button if I do it this way? You can either provide a delegate method for your cell that calls back to your view controller, or you can pass your cell a block to perform when the button is clicked.
as far as i can get u already have a custom cell.. add a button to existing cell and create an IbOutlet for the same in customCell.h file
then in cellForRowAtIndexPath method access the button using its IBOutlet
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
customCell *cell =(customCell*) [tableView dequeueReusableCellWithIdentifier:#"customCell" forIndexPath:indexPath];
[cell.btn setTitle:#"blabla" forState:UIControlStateNormal];
[cell.btn setTag:indexPath.row];
[cell.btn addTarget:self action:#selector(method:) forControlEvents:UIControlEventTouchUpInside];
if(condition)
{
cell.btn.hidden=YES;
}
else
{
cell.btn.hidden = NO;
}
return cell;
}
Do not forget to register for the customCell class in your ViewController class
[tableName registerNib:[UINib nibWithNibName:#"customCell" bundle:nil] forCellReuseIdentifier:#"customCell"];
you can hide or unhide the button as per your requirements as well as add different actions to the button in each class.
Happy Coding..!!
Do vote it if my code was helpful for you.. ;)
I put a tableview in my storyboard, and filled the cell with a button with "0" as the tag. I populated the tableview using an array. Let's just say I have 20 elements in my array, that makes it 20 cells on the tableview. This is the code I'm using to give tags to the button on each cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == _tblCart) {
static NSString *cellIdentifier = #"CartCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
UIButton *btn = (UIButton *)[cell viewWithTag:0];
[btn setTag:indexPath.row];
[btn addTarget:self action:#selector(logTag:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
return nil;
}
I thought my code will work just fine, but actually there is something wrong. On cell 0-5, the button tag is correct. On the following cell the tag will reset again to 0. What am I doing wrong?
There is also another logic problem here, you are reusing table cells, some of which you've changed the tag of the button to something other than 0. So if you get a reused tablecell, there will come a time that the UIButton won't have a tag of zero and therefore you won't be able to change it correctly.
Don't set 0 as a tag identifier to views.
All UIViews have a tag by default 0.
So
[cell viewWithTag:0];
probably will return the contentView of the cell.
Both Flexicoder and l0gg3r are correct. Also, relying on button's tag as row identifier is a bit of a clunky workaround in my opinion. Consider this approach:
- (void)logTag:(UIButton *)sender {
NSIndexPath *indexPath = [_tblCart indexPathForRowAtPoint:[_tblCart convertPoint:sender.center fromView:sender]];
// do your stuff knowing which indexPath the button belongs to
}
Hello I have recently met up with a problem on UITableViewCell
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ContentCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
CloseButton *cButton = (CloseButton *)[cell viewWithTag:20];
[cButton addTarget:self action:#selector(deleteDetector:) forControlEvents:UIControlEventTouchUpInside];
...
return cell;
}
Later, on my delete detector:
-(void)deleteDetector:(id)sender {
CloseButton *cButton = (CloseButton *)sender;
[cButton setHidden:YES];
}
When I start scrolling down to like 1000 cells, the buttons start to appear and some of them starts to disappear.
Ok, so if I understand your question correctly, I assume what's going on is:
You are pressing the button on a cell, which makes the button hidden. Then, you scroll further down, and another cell appears with the button already hidden (even though you haven't pressed the button for that row yet).
This is because your cells are actually being reused, meaning that when one of the cells that has already has the button hidden gets reused, that button will still be hidden (as it is actually the same cell). The 'quick fix' to prove this is to unhide the button in your tableView:cellForRowAtIndexPath: method, like so:
[cButton setHidden:NO];
Do this somewhere after this, obviously:
CloseButton *cButton = (CloseButton *)[cell viewWithTag:20];
This should prevent cells appearing with the button hidden when they shouldn't. However, it will also mean that if you press the button on a cell, and it then goes off screen and comes back on, it will also then show the button again, when you probably don't want it to. You'll have to keep a track of which rows you have pressed the button on in your model somewhere if you don't want that to happen.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MyCell";
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
Movie *movie = [self.movies objectAtIndex:indexPath.row];
cell.title.text = movie.title;
cell.subtitle.text = movie.subtitle;
cell.subtitle.numberOfLines = 0;
[cell.subtitle sizeToFit];
return cell;
}
I am calling reloadData from two places. One is from the end of a loadInitialData function, which is called from viewDidLoad.
A second one is being called from viewDidAppear, although this is inconsequential to my problem, because it existed before it and exists without it.
I initially load 3 rows of sample data, with titles and subtitles. Now what happens is my subtitle text is vertically centered when this window first launches. If I grab the table and scroll is high up, all of a sudden my [cell.subtitle sizeToFit] goes into action, and my text goes to the top vertically, which is desired.
So my issue is... why is the text vertically centered from the beginning? reloadData doesn't work either. When I return from adding a new row, all rows but the newly added row are vertically aligned to top as they should. The new row is incorrectly vertically centered.
Why doesn't this work? Everything seems good. New data is added etc. Via NSLog statements, I have verified numberOfRowsInSection is immediately called after reloadData is called.
So why does the aligning of the text vertically to the top not work?
Thanks!
This is probably because the UITableViewCell has not yet been layed out and so it does not have a size yet. Try doing the sizeToFit in this UITableViewDelegate method
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
I am not sure this will work, but it worth trying.
Add [cell setNeedsLayout]; before you return the cell so it will layout the cell before presentation.
I want to declare the UIButton only once that will show in each table row and then will use button.tag to make button work accordingly.
You will need to have the button created for each table row. You can use prototype cell if you are using Storyboard.
The reason it will not work with single button as a view can be added to one super view at a time. If you add button to second row cell it will be removed from the first row.
Create a Custom cell and design you cell as per your requirement then after in Table View Data Source Method you can set the tag and then after you can create your button method and as per tag use Switch case to do different different action.
Happy Coding!!!
This is a UITableView with UiButton in each row LINK
Code here:-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleIdentifier=#"tableItems";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:simpleIdentifier];
if (cell==Nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleIdentifier];
}
UIButton *tableButton=[UIButton buttonWithType:UIButtonTypeRoundedRect];
tableButton.frame=CGRectMake(140, 5, 60,30);
NSLog(#"%f---%f",cell.center.x,cell.center.y);
[cell addSubview:tableButton];
cell.textLabel.text=[TableArray objectAtIndex:indexPath.row];
cell.textLabel.textColor=[UIColor blueColor];
cell.textLabel.hidden=YES;
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
return cell;
}