Reputation: 5420
I have created aUIButton
programmatically inside the customUITableViewCell
, No. ofUIButtons
inside the cell is dynamic and at first it looks working perfect but when I open all the collapsed cell and scroll the table view UIButton
overlap each other and If I scroll more the the UIButton
in view outside the screen become hidden when thy come back to screen area here is image what it looks like.
I am not posting code here because its big and I don't know which part should I include here. If asked I will post that particular code here.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
InterestTableViewCell *cell = (InterestTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *category= (NSString *)[self.itemsInTable objectAtIndex:indexPath.row];
NSMutableArray *subcat =[[NSMutableArray alloc] init];
NSArray *keys = [cat allKeys];
id aKey = [keys objectAtIndex:indexPath.row];
subcat = [cat objectForKey:aKey];
cell.btnGroupTap.tag = indexPath.row+10000;
NSArray *count=(NSArray *)subcat;
int xoffset;
int yoffset = 0;
for(int i=0; i<count.count;i++)
{
if(i==0)
{
xoffset=0;
}
else
{
if(i%2 == 0)
{
xoffset = 0;
}
else
{
xoffset = 150;
}
}
if(i==0)
{
yoffset = 0;
}
else
{
if(i%2==0)
{
yoffset = yoffset+45;
}
}
NSString *sel = subcat[i][@"selected"];
NSString *key =subcat[i][@"key"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image;
if(![sel boolValue])
{
image = [UIImage imageNamed: @"unchecked.png"];
}
else
{
image = [UIImage imageNamed: @"checked.png"];
}
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(29,18,20,20)];
[imageView setImage:image];
UILabel *lbl1 = [[UILabel alloc] init];
[lbl1 setFrame:CGRectMake(0,5,100,20)];
lbl1.backgroundColor=[UIColor clearColor];
lbl1.textColor=[UIColor blackColor];
lbl1.frame = CGRectMake(40,0,100,40);
lbl1.numberOfLines =0;
[lbl1 setFont:[UIFont fontWithName:@"Roboto-Light" size:12]];
lbl1.text= subcat[i][@"value"];
button.tag= [key integerValue];
[button setTitle:@"" forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
[button setBackgroundImage:image forState:normal];
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
button.frame = CGRectMake(xoffset,20+yoffset,(screenWidth/2)-40,40);
[button addTarget:self action:@selector(CheckAction:) forControlEvents:UIControlEventTouchUpInside];
[button addSubview:lbl1];
[cell.ContainerView addSubview:button];
[cell.ContainerView bringSubviewToFront:button];
}
cell.ContainerView.hidden=YES;
cell.lblCategory.text = category;
return cell;
}
Note: I used [tableView beginUpdates];[tableView endUpdates];
in didSelectRowAtIndexPath
.
Upvotes: 0
Views: 444
Reputation: 5967
As you are using reusable cells
via dequeueReusableCellWithIdentifier
: so if the cell is reused it will be already having the previously added CategoryView
(basically subviews
). You need to remove them first and than ass the new ones, you need to do it as
for (UIView *subview in cell.ContainerView.subViews) {
if ([subview isKindOfClass:[UIButton class]]) {
[((UIButton *) subview) removeTarget:nil
action:NULL
forControlEvents:UIControlEventAllEvents];
[subview removeFromSuperview];
}
}
Add above method inside cellForRowAtIndexPath
: method as-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
InterestTableViewCell *cell = (InterestTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
for (UIView *subview in cell.ContainerView.subViews) {
if ([subview isKindOfClass:[UIButton class]]) {
[((UIButton *) subview) removeTarget:nil
action:NULL
forControlEvents:UIControlEventAllEvents];
[subview removeFromSuperview];
}
}
NSString *category= (NSString *)[self.itemsInTable objectAtIndex:indexPath.row];
NSMutableArray *subcat =[[NSMutableArray alloc] init];
NSArray *keys = [cat allKeys];
id aKey = [keys objectAtIndex:indexPath.row];
subcat = [cat objectForKey:aKey];
cell.btnGroupTap.tag = indexPath.row+10000;
NSArray *count=(NSArray *)subcat;
int xoffset;
int yoffset = 0;
for(int i=0; i<count.count;i++)
{
if(i==0)
{
xoffset=0;
}
else
{
if(i%2 == 0)
{
xoffset = 0;
}
else
{
xoffset = 150;
}
}
if(i==0)
{
yoffset = 0;
}
else
{
if(i%2==0)
{
yoffset = yoffset+45;
}
}
NSString *sel = subcat[i][@"selected"];
NSString *key =subcat[i][@"key"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image;
if(![sel boolValue])
{
image = [UIImage imageNamed: @"unchecked.png"];
}
else
{
image = [UIImage imageNamed: @"checked.png"];
}
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(29,18,20,20)];
[imageView setImage:image];
UILabel *lbl1 = [[UILabel alloc] init];
[lbl1 setFrame:CGRectMake(0,5,100,20)];
lbl1.backgroundColor=[UIColor clearColor];
lbl1.textColor=[UIColor blackColor];
lbl1.frame = CGRectMake(40,0,100,40);
lbl1.numberOfLines =0;
[lbl1 setFont:[UIFont fontWithName:@"Roboto-Light" size:12]];
lbl1.text= subcat[i][@"value"];
button.tag= [key integerValue];
[button setTitle:@"" forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
[button setBackgroundImage:image forState:normal];
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
button.frame = CGRectMake(xoffset,20+yoffset,(screenWidth/2)-40,40);
[button addTarget:self action:@selector(CheckAction:) forControlEvents:UIControlEventTouchUpInside];
[button addSubview:lbl1];
[cell.ContainerView addSubview:button];
[cell.ContainerView bringSubviewToFront:button];
}
cell.ContainerView.hidden=YES;
cell.lblCategory.text = category;
return cell;
}
Note: Also if you are using manual memory management scheme for memory management than you need to properly balance the retain count of your objects, for example after creating any subview
and adding it fire a release
message there. And finally remove it from superview if it's no longer required. I have added these removeFromSuperView
/ release
statements in your cellForRowAtIndexPath
: method.
But as you are using ARC than system will manage the retain /release calls on the object to manage memory
Upvotes: 0
Reputation: 4854
The thing is you are using Reusable cells. Think of it as a shopping cart in the market. You will never know if it is new one, maybe you will get one with products already in it. You should always clean your cell in cellForRowAtIndexPath
and then proceed with your code.
#edit Seems like cleaning your containerView should help. Like:
InterestTableViewCell *cell = (InterestTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[[cell.ContainerView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
Upvotes: 2