简体   繁体   中英

UILabel getting added multiple times on UITableViewCell

I am having a UITableViewCell which is displaying data from a JSON Array consisting of Instagram Pictures. However the UITableViewCell is messed up in the sense that each corresponding Cell has the prior Cells data on top of it. Its more of a UI issue rather than actual web API issue. This issue can best be shown in a picture so I have provided one below 在此处输入图片说明 Here is the code I am using:

   UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"InstaCell"];
    cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Background.png"]];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"InstaCell"];
    }

    NSDictionary *entry = instaPics[indexPath.row];

    //
    // SETUP VIEWS
    //

    // Name
    self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(73, 6, 192, 25)];
    [self.nameLabel setFont:[UIFont fontWithName:@"Helvetica-Regular" size:16.0]];


    // Profile Pic
    self.profilePic = [[UIImageView alloc] initWithFrame:CGRectMake(10, 6, 50, 50)];


    // Date Label
    self.dateLabel = [[UILabel alloc] initWithFrame:CGRectMake(68, 29, 192, 21)];
    [self.dateLabel setFont:[UIFont fontWithName:@"Helvetica-Light" size:12.0]];


    // Like Button
    self.likeButton = [[UIButton alloc] initWithFrame:CGRectMake(68, 279, 18, 18)];
    [self.likeButton setBackgroundImage:[UIImage imageNamed:@"heartShape.png"] forState:UIControlStateNormal];
    [self.likeButton addTarget:self action:@selector(didTapLikeButton:) forControlEvents:UIControlEventTouchUpInside];


    // Comment Button
    self.commentButton = [[UIButton alloc] initWithFrame:CGRectMake(68, 29, 192, 21)];


    // Like Label
    self.likeLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 371, 50, 21)];
    self.likeLabel.font = [UIFont fontWithName:@"HelveticaNeue-Medium" size:14];
    self.likeLabel.textColor = [UIColor orangeColor];


    // Heart Icon
    self.heartIcon = [[UIButton alloc] initWithFrame:CGRectMake(20, 375, 14, 14)];
    [self.heartIcon setBackgroundImage:[UIImage imageNamed:@"heart.png"] forState:UIControlStateNormal];
    [self.heartIcon setTitleColor:[UIColor grayColor]
                         forState:UIControlStateHighlighted];
    [self.heartIcon addTarget:self action:@selector(didTapLikeIcon:) forControlEvents:UIControlEventTouchUpInside];


    // Comment Icon
    self.commentIcon = [[UIButton alloc] initWithFrame:CGRectMake(20, 395, 14, 14)];
    [self.commentIcon setBackgroundImage:[UIImage imageNamed:@"comment.png"] forState:UIControlStateNormal];
    [self.commentIcon setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
    [self.commentIcon addTarget:self action:@selector(didTapCommentIcon:) forControlEvents:UIControlEventTouchUpInside];


    // Comment Text
    self.commentText = [[UILabel alloc] initWithFrame:CGRectMake(-88, 370, 259, 40)];
    [[self.commentText layer] setAnchorPoint:CGPointMake(0, 0)];
    self.commentText.font = [UIFont fontWithName:@"HelveticaNeue" size:14];
    self.commentText.lineBreakMode = NSLineBreakByWordWrapping;
    self.commentText.numberOfLines = 3;
    self.commentText.textColor = [UIColor blackColor];


    // Location Icon
    self.locationIcon = [[UIButton alloc] initWithFrame:CGRectMake(73, 33, 12, 12)];
    [self.locationIcon setBackgroundImage:[UIImage imageNamed:@"location.png"] forState:UIControlStateNormal];
    [self.locationIcon setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];
    [self.locationIcon addTarget:self action:@selector(didTapLocationIcon:) forControlEvents:UIControlEventTouchUpInside];


    // Heart Button
    self.heartButton = [[UIButton alloc] initWithFrame:CGRectMake(40, 465, 25, 25)];
    [self.heartButton setBackgroundImage:[UIImage imageNamed:@"heart.png"] forState:UIControlStateNormal];
    [self.heartButton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];


    // Comment Button
    self.commentButton = [[UIButton alloc] initWithFrame:CGRectMake(220, 465, 25, 25 )];
    [self.commentButton setBackgroundImage:[UIImage imageNamed:@"comment.png"] forState:UIControlStateNormal];
    [self.commentButton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted];


    //
    // ADD DATA
    //

    // Set User Name
    NSString *user = entry[@"user"][@"full_name"];
    [self.nameLabel setText:user];

    // If no Caption
    if (entry[@"caption"] != [NSNull null] && entry[@"caption"][@"text"] != [NSNull null])            {
        NSString *caption = entry[@"caption"][@"text"];
        [self.commentText setText:caption];
    }else{
        NSString *caption = @"";
        [self.commentText setText:caption];
    }

    // Set the number of likes
    NSString *likesCount = entry[@"likes"][@"count"];
    NSString *likes = [NSString stringWithFormat: @"%@", likesCount];
    [self.likeLabel setText:likes];

    // Add Profile Image
    NSURL *imageUrl = entry[@"user"][@"profile_picture"];
    [self.profilePic sd_setImageWithURL:imageUrl completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
        self.profilePic.image = image;
        //Make the Profile Pic ImageView Circular
        CALayer *imageLayer = self.profilePic.layer;
        [imageLayer setCornerRadius:25];
        [imageLayer setMasksToBounds:YES];
    }];

    //NSString *latitude = entry[@"location"][@"latitude"];
    //NSString *longitude = entry[@"location"][@"longitude"];

    //if ([[entry objectForKey:@"location"] objectForKey:@"latitude"] == NSNotFound) {
      // NSLog(@"Contains Location");
    //}

    [self.commentButton addTarget:self action:@selector(commentButtonTap:) forControlEvents:UIControlEventTouchUpInside];
    [self.likeButton addTarget:self action:@selector(likeButtonTap:) forControlEvents:UIControlEventTouchUpInside];

    NSDictionary *instapic = [self.instaPics objectAtIndex:indexPath.row];

    // Comparator to determine if their are any videos availible 
    if (entry[@"videos"] != nil) {
        // Set Videos
        NSLog(@"there are videos: %@", entry[@"videos"]);
        CGFloat width = [UIScreen mainScreen].bounds.size.width;
        _playerView = [[GUIPlayerView alloc] initWithFrame:CGRectMake(10, 65, 299, 299)];
        [_playerView setDelegate:self];

        [[self view] addSubview:_playerView];

        NSString *urlstring = entry[@"videos"][@"standard_resolution"][@"url"];

        NSURL *URL = [NSURL URLWithString:urlstring];
        [_playerView setVideoURL:URL];
        [_playerView prepareAndPlayAutomatically:YES];
    }else{
        // Set Image
        self.instagramPic = [[UIImageView alloc] initWithFrame:CGRectMake(10, 65, 299, 299)];
        NSString *imageUrlString = entry[@"images"][@"low_resolution"][@"url"];
        NSURL *url = [NSURL URLWithString:imageUrlString];
        [self.instagramPic sd_setImageWithURL:url];

    }

    //
    // ADD ALL SUBVIEWS
    //

    [cell addSubview:self.commentButton];
    [cell addSubview:self.nameLabel];
    [cell addSubview:self.profilePic];
    [cell addSubview:self.instagramPic];
    [cell addSubview:self.dateLabel];
    [cell addSubview:self.likeButton];
    [cell addSubview:self.commentButton];
    [cell addSubview:self.likeLabel];
    [cell addSubview:self.heartIcon];
    [cell addSubview:self.commentIcon];
    [cell addSubview:self.commentText];
    [cell addSubview:self.locationIcon];
    [cell addSubview:self.heartButton];

    return cell;

You're adding the labels to the view again every time the frame is loaded. the cellForRowAtIndexPath: method is the wrong place to add custom fields to a cell.

You need to make a custom UITableViewCell subclass and add the fields in there and expose them through either properties or methods and just set the new values in cellForRowAtIndexPath: .

Hope that helps.

When you call dequeueReusableCellWithIdentifier you may be given a cell that has already been displayed at another location in your table and then scrolled away. That's kind of what "reusable" means for cells.

You can either create a .xib file that contains your custom cell with all its views and just set data in your method or you can implement prepareForReuse to remove the views you are adding.

You should really be subclassing UITableViewCell instead of creating views inside the cell itself.

However, if you really dont want to subclass (sublcassing is great). Create objects inside the cell creation method

    if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"InstaCell"];
UIButton *button = // etc...

        }

Stop using self. objects inside cell too, if you are creating multiple copies, then dont make them global. Keep them local.

Using dequeueReusableCellWithIdentifier the UITableViewDataSource protocol will reuse cells, so you are adding views to cells that you already added views before.

Maybe not the best, but the simplest solution is to remove the subViews already added, before adding new ones.

before adding subviews try this:

for (UIView *subView in cell.contentView.subviews) {
    [subView removeFromSuperview];
}

One more thing, you should be adding subview to cell.contentView

EDIT

Like Tim comment:

Adding and removing on every pass is wasteful, and could be risky if there are multiple places where views are inserted into rows.

EDIT

Your best solution is to create a custom UITableViewCell

YourCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"YourCellIdentifier"];
if (!cell) {
     cell = [[YourCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"YourCellIdentifier"];
}

Then you could create a Xib and connect IBOutlet .

Then, for example if you create an outlet for nameLabel , you could do something like this:

[cell.nameLabel setText:entry[@"user"][@"full_name"]];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM