UITableViewCell weird behavior - ios

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.

Related

cellForRowAtIndexPath method custom button show 2 time

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.. ;)

Get tableview row on cell button tap

I have a tableview with cells (not custom), and each cell has a button (among other things).
Depending on the cell, the button that is created is different. I have 3 different types of cell/button, Rate/View/Edit (I'm not sure that's at all relevant)
This button is only used for this:
[button addTarget:self action:#selector(rateEvent:) forControlEvents:UIControlEventTouchUpInside];
The selector is different for each button (rateEvent, viewEvent, editEvent).
Here is an example, they're all 3 fairly similar and start the segue sequence:
- (IBAction)viewEvent:(UIButton*)sender
{
[self performSegueWithIdentifier:#"fromHomeToDetails" sender:self];
}
My didSelectedRowAtIndexPath saves the details of a meeting in the selectedMeeting object.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedMeeting = [_nextMeetingsArray objectAtIndex:indexPath.row];
}
The segue sends selectedMeeting to the next controller.
My issue : The meeting that is sent depends on the selected cell. That means the user has to select a cell and THEN tap the button to get the correct details on the next page. What can i do to get the correct indexpath of a tapped button inside a cell?
I tried to add parameters to the viewEvent method, to make it look like -(void)viewEvent:(int)index:(UIButton*)sender; but it doesn't work in the #selector(viewEvent:).
The solutions i can imagine but not create are :
- Manage to get the indexpath of the cell of a tapped button and send it to my viewEvent method, somehow.
- Create a customCell and/or use an accessory, so i've read here and there.
- Force row selection when i tap the button, but that also requires to know the index of said row.
Both seem "too complicated" for something that (should?) be fairly simple. I'm pretty sure any experienced programmer will have an obvious easy answer that I haven't learned yet, and i'd rather ask for it than implement something heavier than it should be.
Also, if you have any comment/criticism on how i've done that, i'm all ears :)
Thanks for your time guys, as always, i'm very grateful.
EDIT :
cellForRow method :
Note : i removed everything that has to do with labeling. Because i have different buttons there are multiple if{} statements but they are of no influence in my opinion. Also, the cell is based on a storyboard cell with a tag of 228 ; after creation a new tag is set so it shouldn't influence. Also, i have a cap of 50 items in tableview (set from webservice) so there is no way the indexpath reaches >50.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *nextCell = [self.tbvNextMeetings dequeueReusableCellWithIdentifier:#"tbNextCell" forIndexPath:indexPath];
UIButton *bt= (UIButton*) [nextCell viewWithTag:228];
[bt setTitle:#"Edit" forState:UIControlStateNormal];
[bt addTarget:self action:#selector(editEvent:) forControlEvents:UIControlEventTouchUpInside];
[bt setTag:indexPath.row];
return nextCell;
Add tag to button as indexpath.row, in cellForRowAtIndexPath() method. Then in selector method get sender tag. And pass in
NSIndexPath *path = [NSIndexPath indexPathForRow:sender.tag inSection:yoursection];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:path];
Edit : Setting the cell with a tag of 228 at first and then switching it to the value of indexpath made its creation fail.

clicking button on tableviewcell clicks cell not button

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.

iOS Custom button in table cell gets dimmed when highlighted

I have a button added to a UITableViewCell, at the end. When highlighted, I have a custom highlight layer with transparency on the end. However, the button still gets dimmed, though it's still working. But the user can get the idea it has become inactive. I would like the button to stay as it is, even as the cell is highlighted. I would like to understand why and how the button gets dimmed, even if the highlight layer has full transparency there.
UIButton in UITableViewCell
overriding some stuff to fix this.
I tried, but I don't know how to get 'yourButton' to be the button that is in the cell?
This finds the button and sets its highlighted state to NO.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
for(UIView *views in cell.subviews)
{
if(views.tag == indexPath.row){
for(UIButton *deKnop in views.subviews)
{
deKnop.highlighted = NO;
}
}
//if ( [views isKindOfClass:[UIButton class]] ) {
//do your code
//[subviews setImage:[UIImage imageNamed:#"PENCIL.png"] forState:UIControlStateHighlighted];
//}
}

iOS) HIding Keyboard in a cell in UITableView

-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"searchCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
searchField = (UITextField *)[cell viewWithTag:10000];
[searchField resignFirstResponder];
}
Okay, I have a cell with a identifier name of "searchCell". This cell contains one single UITextField with tag 10000 that pops up a keyboard on the bottom of the screen. When a user touches another cell, the keyboard must be hidden so that the user can have larger space to scroll up and down.
However, when a keyboard has popped up and a user touches(select) a cell, the code above is called but not working... :( It seems like the assigned UITableViewCell is not the one that the user is currently using. What am I doing wrong here?
Make your class a delegate of UITextField
Go to the Storyboard file, click on the text field and go to connections inspector
Under outlets, connect the delegate to the View Controller
Run it in simulator. It will work

Resources