Sandeep Singh
Sandeep Singh

Reputation: 826

Strange Behaviour of Table Cell

I am just implementing a table view in my app. I have done this multiple times but this time the table cell shows the repeating data and speed of table scrolling is not good also. Just posting my code for table. Any help to prevent cell data repetition and scroll speed optimisation will be appreciated.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    int count = [array count];

    if (count%3 == 0)
    {
        return count;
    }
    else
    {
        count = count/3+1;
    }
    NSLog(@"Row count is%i",count);
    return count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *MyIdentifier = @"MyIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier];
    }
    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 490, 221)];
    int x = 15;
    int y = 15;
    int p = 10;
    int q = 10;
    for (int i = 0; i < 3; i++)
    {
        if ( indexPath.row*3+i < [array count] )
        {
            UIImageView *img = [[UIImageView alloc] init];
            UIButton *btn = [[UIButton alloc] init];
            [img setImageWithURL:[NSURL URLWithString:[array objectAtIndex:indexPath.row*3+i]]
                placeholderImage:[UIImage imageNamed:@"India.png"]
                         success:^(UIImage *image) {}failure:^(NSError *error){}];
            img.frame = CGRectMake(x, y, 140, 201);
            btn.frame = CGRectMake(p, q, 150, 211);
            btn.tag = indexPath.row*3+i;

            [btn setBackgroundImage:[UIImage imageNamed:@"Picframe_N.png"] forState:UIControlStateNormal];
            [btn setBackgroundImage:[UIImage imageNamed:@"Picframe_S.png"] forState:UIControlStateHighlighted];
            [btn addTarget:self action:@selector(Movie_detail:) forControlEvents:UIControlEventTouchUpInside];
            [testView addSubview:img];
            [testView addSubview:btn];

            x = x+160;
            p = p+160;
        }
        else
        {
            NSLog(@"No data");
            break;
        }
    }
    [cell addSubview:testView];
    return cell;
}

The Things updated in cell is for the purpose to add 3 buttons in single cell. Nothing else.

Upvotes: 0

Views: 186

Answers (5)

Lithu T.V
Lithu T.V

Reputation: 20021

SUGGESTION

Use custom cell

Fix :

Creating and adding the subview is to be included inside the braces where the cell is allocated

ie

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier];
         //CREATING AND ADDING SUBVIEW SHOULD BE HERE
    }
          //Change in values is taken care here

REASON

Otherwise every time a subview is created,allocated all objects and added above when table is scrolled

REFER

Apple Docs

Upvotes: 2

Totumus Maximus
Totumus Maximus

Reputation: 7573

The problem you are facing is that you add a UIView to every cell that comes into the screen. However you are reusing the cells so the old 'added' views are still on them. The repetition of the data is because there are multiple layers of testviews on a cell when you scroll.

You should either make a CustomCell that includes the testview that you are adding at every cellforrow: OR add the testview to the cellviews when the cell is still a nil-value so that if it gets reused you won't add yet another testview to the cell and they overlap. The examples of those are written in other answers here but are found on the web everywhere.

Not recommended but: Another quick but dirty fix is to just remove all subviews from the cell (or any subview that you add the testview to) for(UIView *v in [cell(.contentView) subviews]){ [v removeFromSuperView]; }

Upvotes: 1

Nirav Gadhiya
Nirav Gadhiya

Reputation: 6342

hello this problem is normal when you are using dequeueReusableCell

just make change as i listed below in following methode..

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *MyIdentifier = @"MyIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    UIView *testView;
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier];
        testView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 490, 221)];
        testView.tag = 111;
        [cell addSubview:testView];
        [testView release];//For Non ARC
    }
    else
    {
        testView = [cell.contentView viewWithTag:111];
        for(UIView * vv in [testView subViews])
        {
            [vv removeFromSuperView];
        }
    }
    int x = 15;
    int y = 15;
    int p = 10;
    int q = 10;
    for (int i = 0; i < 3; i++)
    {
        if ( indexPath.row*3+i < [array count] )
        {
            UIImageView *img = [[UIImageView alloc] init];
            UIButton *btn = [[UIButton alloc] init];
            [img setImageWithURL:[NSURL URLWithString:[array objectAtIndex:indexPath.row*3+i]]
                placeholderImage:[UIImage imageNamed:@"India.png"]
                         success:^(UIImage *image) {}failure:^(NSError *error){}];
            img.frame = CGRectMake(x, y, 140, 201);
            btn.frame = CGRectMake(p, q, 150, 211);
            btn.tag = indexPath.row*3+i;

            [btn setBackgroundImage:[UIImage imageNamed:@"Picframe_N.png"] forState:UIControlStateNormal];
            [btn setBackgroundImage:[UIImage imageNamed:@"Picframe_S.png"] forState:UIControlStateHighlighted];
            [btn addTarget:self action:@selector(Movie_detail:) forControlEvents:UIControlEventTouchUpInside];
            [testView addSubview:img];
            [testView addSubview:btn];

            x = x+160;
            p = p+160;
        }
        else
        {
            NSLog(@"No data");
            break;
        }
    }

    return cell;
}

TRY THIS....

Upvotes: 0

Firdous
Firdous

Reputation: 4652

Repeating data in different cells might be due to same "CellIdentifier", try having different "CellIdentifier" for different cell view types. I can see different cell view types since you are having some condition block in your code.

static NSString *MyIdentifier;

MyIdentifier = @"Type1";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier];
    }


MyIdentifier = @"Type2";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier];
    }

Upvotes: 0

iphonic
iphonic

Reputation: 12719

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *MyIdentifier = @"MyIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:MyIdentifier];

        UIView *testView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 490, 221)];
    int x = 15;
    int y = 15;
    int p = 10;
    int q = 10;
    for (int i = 0; i < 3; i++)
    {
        if ( indexPath.row*3+i < [array count] )
        {
            UIImageView *img = [[UIImageView alloc] init];
            UIButton *btn = [[UIButton alloc] init];
            [img setImageWithURL:[NSURL URLWithString:[array objectAtIndex:indexPath.row*3+i]]
                placeholderImage:[UIImage imageNamed:@"India.png"]
                         success:^(UIImage *image) {}failure:^(NSError *error){}];
            img.frame = CGRectMake(x, y, 140, 201);
            btn.frame = CGRectMake(p, q, 150, 211);
            btn.tag = indexPath.row*3+i;

            [btn setBackgroundImage:[UIImage imageNamed:@"Picframe_N.png"] forState:UIControlStateNormal];
            [btn setBackgroundImage:[UIImage imageNamed:@"Picframe_S.png"] forState:UIControlStateHighlighted];
            [btn addTarget:self action:@selector(Movie_detail:) forControlEvents:UIControlEventTouchUpInside];
            [testView addSubview:img];
            [testView addSubview:btn];

            x = x+160;
            p = p+160;
        }
        else
        {
            NSLog(@"No data");
            break;
        }
    }
    [cell addSubview:testView];
    }

    return cell;
}

You should not initialize anything outside the block where your cell is initialized, because when you scroll your tableview the method cellForRowAtIndexPath get called everytime, and your view testview is getting created everytime..

Outside the cell initialization you should only update the values to be shown in the cell..

Hope above works..

Edited But better approach I would suggest try to create a Custom Cell so that you can easily access the components added to your cell to update their values as your tableview scrolls..

Thanks.

Upvotes: 0

Related Questions