addSubview to specific uitableviewcell on select - uitableview

I have a tableview and I want to add an imageview to the contentView of the cell at the row it was selected in.
This is my current code and when I click any cell it only adds the imageView to the last row rather than the row I click on.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
playIcon = [[UIImageView alloc]initWithFrame:CGRectMake(20, 22, 9, 12)];
UIImage *image = [UIImage imageNamed: #"cell_play.png"];
[playIcon setImage:image];
[cell.contentView addSubview:playIcon];
}

You can do like this
[[tableView cellForRowAtIndexPath:indexPath] addSubview:playIcon];

First, you have not identified a cell at a particular row. Since your compiler didn't complain, I assume that cell is an ivar. It is pointing to the last cell that it was pointed to, which very well may be the last cell in the table.
You have to be careful that you don't set the content of a cell outside of the UITableview methods, including the UITableView method cellForRowAtIndexPath:`. This is described in a recent answer I provided at this link.
So if you looked at that answer, you will have read that the tableview methods make sure the cell is rendered correctly even when the tableview scrolls and cells appear and disappear. I recommend that you set up your data source with some kind of tag or property that you can use to see that this image needs to be present. That way, it will be there even if you scroll the cell so it dissappears and reappears.

work for me with UIcollectionView and UItableviewcell in Swift 2.0:
CV_Posts.cellForItemAtIndexPath(index)?.addSubview(imag_curtir)

Related

What is difference between deselectRowAtIndexPath and cell setSelected?

What is difference between
[tableView deselectRowAtIndexPath:indexPath animated:NO];
and
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexpath];
[cell setSelected:NO];
???
In a UITableView a cell does not match a specific piece of your data. It can (and should most of the time) be reused and it is nil when not visible.
deselectRowAtIndexPath will set the indexPath as 'not selected' in your tableview, so when you scroll back and forth to that cell, it will stay unselected, because you told your tableview that whatever the cell you display at that indexPath it should be unselected.
With UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexpath];
[cell setSelected:NO]; you set the cell as unselected. However that cell can be used for other pieces of data, and it can even be nil if this indexPath is not displayed.
First one is programmatically deselecting the cell. So it will un-highlight the cell if the user has selected it already.
As for the second bit of code, I believe that is just a pointer or reference to one of the cells in your table view. You can use this code to edit a cell OUTSIDE of any of the table view delegate methods. So if you wanted to edit/update a label on one of your cells but from a random method (not a table view delegate method), then you could use that code to reference the label text property.
I think you should also check out the Apple Developer Library website. It explains all the different table view method/properties/etc in lots of detail:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/
The concepts of "selected" is different for a tableview and for a cell. The tableview can have one or more rows selected that changes the state of the tableview, however changing the tableview cell selected state only affects its appearance and nothing else.

UITableView over UITableViewCell didSelectMethod

This must be stupid question,
Some how I know the reason but difficult to find solution.
So any help will be welcome..
What I am having is, one UITableView with header.
Header contains the Question and UITableViewCell contains the options to question.
Each cell is having 3 controls,
2 Labels and 1 button.
1 label contain Option and other contains its answer.
To match the answer you have to select option from drop down, which is opened when button from that cell is clicked.
That drop down is again a UITableView.
Which options.
So that DropDownTableView is added over UITableViewCell.
but problem is that when I open drop down on that cell, the table goes beyond boundary of cell,
So DidSelectMethod of DropDown table is not getting called.
I can't increase the height of BaseTableVieCell, but I want to select option from DropDownTable.
What should I do.
I tried bringSubviewToFront, and also disabling the baseTableView when Button is clicked.
But didn't helped.
Is there any other way to achieve the task.
Thanks for help.
Here is the picture which will give detail idea.
I am not able to select option "A", "B" , "C" as they go out of boundary of cell.
Thanks in advance.
You just need to resize the cell whose button is clicked as follows:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CGRect rect = cell.frame;
rect.size.height = 150.0;
ht = 150.0; // declared previously. you may check in the attached project
selected = indexPath.row;
[cell setFrame:rect];
[tableView beginUpdates];
[tableView endUpdates];
}
I have just given you an idea on how you will resize the cell. Here I have taken a static height(150.0). Instead of that you will have to give the height of your inner tableView that gets dropped down on UIButton click.
You can find demo project to change the cell height dynamically here.
Hope that helps.

Keep the color of text's cell when come back to table

I changed the color of text for the cell clicked in the table. But after the cell is clicked, when i come back to table the text of cell has the original color. Could you give me an advice?
This is the code in "didSelectRowAtIndexPath"
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.highlightedTextColor = [UIColor blueColor];
Thank you
after the cell is clicked, when i come back to table the text of cell has the original color. Could you give me an advice?
You need to have the color for each cell stored somewhere other than in the table, so that you can reproduce the colors you want anytime the table redraws itself. Typically, you'll have some sort of data structure that stores the table's data, and that's usually the right place to save any changes the user makes. The table view's data source should have a -tableView:cellForRowAtIndexPath: method that sets the color according to what you've saved, along with any other cell attributes.
This is happen because the cells are reused, so lets say when you change text colour property of some cell it will be affected as you expect but when you scroll and that cell disappear off the screen it will be put to reuse pool and if it appears again on the screen table view takes some cell from the reuse pool but it's properties will be different so the colour won't persist.
You should keep somewhere, for example in NSMutableArray, info about which table was clicked.
You can add an index path to the array when you click the cell and in cellForRowAtIndexPath: check is this indexPath in the array and if it is change appropriate property.
The problem is that iOS throws away your cell if you scroll away and recreates it when it's needed (you scroll back to the cell).
If I were you, I would subclass UITableViewCell and overwrite
- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
In there you would have
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected: selected animated: animated];
self.textLabel.textColor = selected ? [UIColor blueColor] : [UIColor blackColor];
}
Since iOS UITableView remembers which cell is selected, this should work fine, even when it's recreated.
The reason it's happening is what others are saying: cells are reused.
Storing selection state or color will work, however if you just need to make sure that selected cells have a different color for a label than non-selected cells, there's a way that does not require to use a supporting data structure.
You just need to check if the cell being setup at - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath is currently selected or not, and that can be achieved with [tableView indexPathForSelectedRow] if your table uses single selection, or [tableView indexPathsForSelectedRows] if it uses multiple selection.
The last case requires you to find the current indexPath in the returned array, and might be slower than using the supporting array.
But if the selection is simple, then this solution is probably faster, uses less memory and is easier to read (IMO).

tableView reloadData will not remove previous UITextView that is programmatically placed

I've got a UITableView with several different elements added programmatically. The one I'm having trouble with is the UITextView that displays correctly with correct color, size, font, etc... I have a button in one cell that increases the size of the font in the UITextView in another cell. It works fine and has no issues. The numerical value is placed in a Plist, and when you leave the view with the table and come back the size changes perfectly.
I've placed a reloadData in the button which does reload the table and gives the textView new size and resizes it to fit the new content plus resizes the cell perfectly. The issue I'm having is that when the reloadData is called, the old textView remains. So I have two texts, at two different sizes, or three or four and so on. How can I remove the previous textView when it's not set to global?
Everything is set up exactly how one would expect:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
// cell with textView. Everything is instanced and created for just that cell with tags
UITextView *t = [self setSizeAndTextOfTextView];
[cell.contentView addSubview:t];
// cell with button. simple, alloc's and init inside cell. Calls method in same class
cell.contentView addSubview:button];
//method to increases font size
write to Plist the new size
[self.tableView reloadData]; <-- tableView is iboutlet that does reload table
How are you getting the cell in the first place? Are you reusing? If you are you don't want to add the textview as a subview again you want to retrieve the existing one and adjust it
UPDATE:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if ([cell.contentView viewWithTag:1]) {
UITextView *t = (UITextView *)[cell.contentView viewWithTag:1];
//This version will take an existing textview and just resize it
[self setSizeAndTextOfTextView:t];
} else {
//This version creates a new text view
UITextView *t = [self setSizeAndTextOfTextView];
t.tag = 1
[cell.contentView addSubview:t];
}
You'll probably need to do something similar with you button as well
The reloadData won't wipe the existing cells, just the data displayed, so you'll get an old one to reuse
You may consider creating a custom subclass of UITableViewCell and associate that with your cell identifier. In your subclass, override the prepareForReuse method to set the cell back to a neutral state. Since cell objects are reused but are only initialized once, prepareForReuse is available to restore an already existing cell to its freshly initialized state.

Removing old data from reusable cell

I have a uitableview with each cell having a scroll view as the subview.
the scrollview has a bunch of images in it.
so when i change the data in the data source and after calling the reload table
the images doesn't change but when i remove the dequeue the new data is reloaded.
is there any method to remove the contents in the dequeue so that i don't get the old data
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"looser"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
scrollview=[[myscrollView alloc]initwitharray:imagearray];
[cell.contentView addSubview:scrollview];
}
}
A tableview works as follows:
It has room for a certain amount of cells on the screen, let's say 7 as an example. The tableview will ask you for the 7 cells of indexes 0 through 6.
If the top cell leaves the screen by scrolling, it will be placed in the reusable cell queue. There are now 6 cells on the tableview.
A new one comes up at the bottom now, the tableview asks for the cell at index 7. You call dequeueReusableCell, and you get the one that was at the top earlier.
The tableView has no idea what your cell is like, as it can be subclassed, so it will not make any changes to it. It is up to you to use your knowledge of how the tablecell is constructed to empty it, then fill it with the correct new data.
The reason tableview works like this is for performance. In stead of having maybe 100 views that would have to be checked (or mostly, ignored, which also costs time) for every scroll movement, it has a maximum of 7.
So in short, no. There are no default methods to remove data from reusable cells in UITableView, since UITableView can not and should not know what kind of cells they are. It is up to you to clear the cells when the tableview gives them to you.
Create a custom cell and it generates a method
- (void) prepareForReuse{}
Which do you cleanse all data from a cell and the output will be an empty cell.
No, not while the cell is in the cache. When you dequeue a reusable cell you should clear out the old data first before using it again.
Maybe you should just remove the stuff you don't want.

Resources