How to remove Views from UITableView custom row on PrepareForReuse? - ios

I have a UITable view with a random number of UIImageView in every Single row. In the costruction of the single row, I've used [self addSubView: xxx] and a for cycle to add every UIImageView i need to add (my model has an array of URL). But now I've noticed that when the UITableView reuse the rows and it doesn't clean the UIImageViews added.
I've tied to manually remove them in method onPrepareForReuse as in the code:
if(_messageContentsFrames != nil){
for(NVChatMessageContent *singleContent in _messageContentsFrames){
[singleContent removeFromSuperview];
}
}
But it gives me error. How can i completely reset the view when it is going to be reused?

You can remove these imageViews in -tableView:cellForRowAtIndexPath: method. That always worked for me.
By the way, do you really need to reuse cells if you make such work with it. Wouldn't it be easier to create new cell?
Or it would be better not to remove imageViews, but reconfigure them on reusing and remove those views, that cell doesn't need.

Option 1. Set tag to your UIImageView (use: imageView.tag = 123456) and then in tableView:cellForRowAtIndexPath: you should get the specific view using:
id imageView = [self.view viewWithTag:yourInteger];
[imageView removeFromSuperview];
Option 2. Use:
for( UIView *view in cell.subviews) {
if ([view isKindOfClass:[UIImageView class]]) {
[view removeFromSuperView];
}
}

Related

UIView is overlapping / creating again in cellForRowAtIndexPath

I have UITableViewCell that contains UIView (lets call it CPView) which is created while cellForRowAtIndexPath is called. CPView is just a plain coloured view and for every cell its width is different (that's why needed to create in cellForRowAtIndexPath).
Problem is
1)The CPView 's colour gets darker every time cell loads (May be due to every time that cell creates the same view so overlapping effect).
2) The cell overlaps / inherits other cell's CPView (we can see this because of light and dark colour of two CPView).
How can I prevent cell to recreate if it already exist or creation of this CPView again?
Edit
- (void)configureCell:(CreditDebitCell *)cell atIndexPath:(NSIndexPath *)indexPath {
//other code
UIView * CPView;
if (CPView){
CPView =nil;
}
else
{
CPView = [[UIView alloc] initWithFrame:CGRectMake(cell.bounds.origin.x, cell.bounds.origin.y, cell.frame.size.width*[self.percentArray[indexPath.row] floatValue] ,cell.frame.size.height )];
[CPView setClipsToBounds:YES];
[CPView setBackgroundColor:[UIColor colorWithRed:107/255.0 green:15/255.0 blue:47/255.0 alpha:0.5]];
[cell addSubview: CPView];
}
}
The issue here is reuse of the cells - and therefore you get multiple views added to your cell view.
You can:
-remove subview
-check if subview exists and do/don't do anything.
You can check if the subview is there by going through subviews:
for (UIView *v in cell.contentView.subview) {
if ([v isKindOfClass:[CPView class]]) {
// remove or flag that it exists
}
}
But I think that you should handle this in your cell - not your view controller that implements table view delegate. Better tell cell to use some view/hide some view based on some kind of logic then to do that inside cellForRowAtIndexPath
According to your i question(without cellforRowAtIndexpath) i can assume that you should check every time something like in cellForRowAtIndexPath
if(cpView){
cpView = nil;
}
// alloc again with required size for particular row.
Make a subclass of your UITableViewCell and make a property of it that will reference your CPView. This will now let you have a better control whether your subclassed cell does / doesn't have any CPView that needs to be added.

Remove UILabels from UITableViewCell and add them again

I'm removing labels from a UITableViewCell because i don't need them in that particular cell. The problem is when the cell is reused i need them but they were removed before.
if (post.blockContent == TRUE) {
[cell.titleLabel removeFromSuperview];
[cell.contentLabel removeFromSuperview];
}
How do i add them again to the UITableViewCell?
I remove them because i have constraints linking everything with a dynamic cell height and i can't simply hide them because that will just make a empty space in the middle of the cell.
do like
// set visibile for all cell
[cell.contentView addSubview:cell.titleLabel];
[cell.contentView addSubview:cell.contentLabel];
// when contindition statisfy it will be hide
if (post.blockContent == TRUE) {
[cell.titleLabel removeFromSuperview];
[cell.contentLabel removeFromSuperview];
}
choice-2
cell.titleLabel.hidden = NO;
cell.contentLabel.hidden = NO;
if (post.blockContent == TRUE) {
cell.titleLabel.hidden = YES;
cell.contentLabel.hidden = YES;
}
the tableview reused the cell.
because this reason you cant used removeFromSuperview because all the cells that used the same instance will remove the labels.
the solution is the used constraint.
you need to wrap the labels to view, and the other objects will have constraint that skip over the view and reduce the constant of the cell.
in the heightForRow you need to calc the height without the view .
changed priority at runtime , its the main idea for the solution.

Stretch UIView over multiple UICollectionViewCells in UIScrollView

I have a UIScrollview with a UICollectionview in it which has multiple custom UICollectionViewCells.
What a I want is to stretch a UIView over multiple cells.
I tried to use: cell.clipToBounds = NO; which is working but when I scroll to left and scroll back the expanded part of the UIView is being cut off again.
I guess it has something to do with dequeuing of the cells which aren't used. Can I assign the expanded part to the new cell so that it won't get deleted or sth?
I had a former problem where Cells got duplicated therefor I had overwritten the method prepareForReuse of my custom UICollectionViewCell-Class.
-(void)prepareForReuse
{
for(id aView in [self.contentView subviews])
{
if ([aView isKindOfClass:[MyCustomUIView class]])
{
[aView removeFromSuperview];
}
}
}
Any advice and help will be thankfully appreciated.
If your cell.clipsToBounds = NO is working, but only the first time, I agree that the problem probably has to do with cell reuse. If you are overriding -prepareForReuse, you probably want to set self.clipsToBounds = NO in there. Then, in -collectionView:cellForItemAtIndexPath:, set clipsToBounds to YES or NO every time as needed.

How to remove content from UITableViewCell but still have separator left?

In my app, i have table view in which i am reloading data based on Business logic so it was overlapping earlier then i write this piece of code to remove content before drawing:
for(UIView *view in cell.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}
And now its removing everything including cell separators. Any idea how to prevent it??
Thanks,
Remove subviews from [cell contentView]
If you don't know what are you doing, you should never add views or remove views from the cell directly. Use only contentView, backgroundView and selectedBackgroundView.
However, there is rarely a use case when you should remove all the views from a cell. Why don't you just create a new cell (or reuse one)? Or just set the hidden property to YES for the subviews?

Labels are lingering in my reusable table cells

I have a table whose cells contain labels. Whenever I dequeue a reusable cell, the old labels are still lingering on it. I was able to remove them with this:
for(int a=[[newcell subviews]count]-1; a>=0;a--)
{
if([[[[newcell subviews]objectAtIndex:a]class] isSubclassOfClass:[UILabel class]])
{
[[[newcell subviews] objectAtIndex:a] removeFromSuperview];
}
}
But when I select the cell, I can see the old text on top of the new. I tried this:
[[newcell.selectedBackgroundView subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];
[[newcell.backgroundView subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];
But it didn't work. How can I make the old labels disappear from the selected cell as well as the regular view of the cell?
Subclass UITableViewCell (if you aren't already). Override prepareForReuse and remove the labels there. Might work
This kind of problem tends to happen when you add subviews to your cells in cellForRowAtIndexPath: regardless of whether it's being dequeued or newly created. As a result, you end up creating a new subview each time the row is reused, and the old subviews accumulate.
What you instead want to do is to use the same subview each time, but just set the relevant attributes (e.g., labels or color) each time. Check out the answers to How do I clear a cell completely when I reuse it? to see some possible approaches.
I kinda did what Yuji suggested. Instead of putting in new labels on each iteration, I checked whether the cell contained labels and then either edited the labels if they were there or put them in if they weren't. Code goes like this:
if([[newcell.contentView subviews] count]>=2 && [[[[newcell.contentView subviews] objectAtIndex:0]class] isSubclassOfClass:[UILabel class]] &&
[[[[newcell.contentView subviews] objectAtIndex:1]class] isSubclassOfClass:[UILabel class]])
{
//change the text of the labels
}
else
{
//add the labels to the cell
}

Resources