UITableViewCell错过了加载一些本地图像/文本

时间:2014-06-26 20:00:01

标签: ios objective-c uitableview uiimageview

我有一个自定义的表视图单元格,用于加载缩略图,文本和文本的背景图像。我正在开发一个聊天应用程序,Cell正在发送/接收消息屏幕中。该单元基本上显示发送/接收。以下是有关项目和问题的更多详细信息。

  1. 我有两张背景图片。一个是发件人,另一个是接收器,这些图像会根据文本大小自动调整大小。
  2. 当我发送/接收小信息(1行)时,信息会正确显示。
  3.   

    然而,当我尝试发送/接收多行消息时,有时背景图像丢失,有时文本丢失(对于某些图像),当我滚动时,这些图像/文本会出现一些。

    我每次都使用 [UIImage imagedNamed:] 加载背景图片。

    在我看来,问题是由于记忆,因为大约6-8个细胞一直可见。请帮助我解决问题。

    修改

    添加一些代码

    -(UITableViewCell *)tableView:(UITableView *)tblView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        MyCell *cell = [tblView dequeueReusableCellWithIdentifier:@"myCell"];
    
        //Setting background image view of cell
        [cell.bgImageView setImage:[[UIImage imageNamed:@"chat_box2.png"] stretchableImageWithLeftCapWidth:0 topCapHeight:40]];
    
        String message = ........;
        CGSize textSize = CGSizeMake(250, 1000);
    
        CGSize size = [message sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:textSize];
    
        size.width += 9;
    
        [cell.messageText setText:message];        
    
        [cell.messageText sizeToFit];
    
        [cell.messageText setText:message];
    
        //Setting frames of background Image View and message Text to our desired frame (**size** is calculated in the above lines)
        [cell.bgImageView setFrame:CGRectMake(79,5, cell.bgImageView.frame.size.width, size.height+18)];
    
        [cell.messageText setFrame:CGRectMake(98, 13, size.width, size.height)];
    
        return cell;
    }
    

    注意:大小计算也在 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 中完成,以便调整单元格大小相应

4 个答案:

答案 0 :(得分:0)

是的,问题是由于细胞可重用性。当您deque Tableviewcells时,当系统尝试重新使用旧的tableviewCells时,内容将变为混合。您应该做的是在cellForRowAtIndexPath委托中将您的单元格的所有值设置为:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     //All Initialization code
     .
     .
     .


     //Set all the values of your Custom Table View Cell here
     cell.image = yourImage;
     cell.text = "your text";
     cell.backGroundImage = yourBackGroundImage;
     cell.TimeLabel.Text = "time value";
}

希望这应该有所帮助。如果您有进一步的疑问,可以随意询问。

答案 1 :(得分:0)

尝试在-tableView: cellForRowAtIndexPath:委托方法中设置MyCell内的图像,文本和所有内容。

我可以看到你把自己标记为已解决。如果它工作得那么好。但是有一些事情你应该肯定改进和改变。有我的建议。

我认为你不必在initWithCoder:中做任何事情。您可以留下故事板来处理。以下是我认为你应该做的代码:

<强> MyCell.h

// define enum for type of cell
typedef NS_ENUM(NSInteger, MyCellType) {
    MyCellTypeSender,
    MyCellTypeReceiver
};

@interface MyCell : UITableViewCell

@property (nonatomic, assign) MyCellType cellType;
@property (nonatomic, strong) NSString *message;

- (void)fitToSize:(CGSize)size;

@end

<强> MyCell.m

@implementation MyCell

// As you can see image is implemented inside the cell in setter of cellType
-(void)setCellType:(MyCellType)cellType {
    if (_cellType != cellType) {
        _cellType = cellType;
        UIImage *bgImage = [UIImage imageNamed:(cellType == MyCellTypeReceiver) ? @"receiverImg" : @"senderImg"];
        self.bgImageView.image = [bgImage stretchableImageWithLeftCapWidth:11 topCapHeight:23];
    }
}

-(void)setMessage:(NSString *)message {
    if (![message isEqualToString:_message]) {
        _message = message;
        self.messageLabel.text = _message;
    }
}

-(void)fitToSize:(CGSize)size {
    self.messageLabel.frame = CGRectMake(98, 13, size.width, size.height);
    self.bgImageView.frame = CGRectMake(79,5, size.width+32, size.height+18);
}

@end

在您的文件中,您使用以下代码实现表的委托和数据源方法:

-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *message = @"some message ....";
    CGSize size = [self sizeForText:message];
    return size.height;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:@"myCell"];
    CGRect cellFrame = [tableView rectForRowAtIndexPath:indexPath]; // Do not calculate the size again. Just grab cell frame from current indexPath
    [cell fitToSize:cellFrame.size]; // You set the content of the cell in MyCell by passing size of cell
    cell.cellType = MyCellTypeRecever; // Or MyCellTypeSender whichever you decide
    cell.message = @"some message ....";

    return cell;
}


-(CGSize)sizeForText:(NSString*)str {

    NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:18.f]};
    CGSize maxSize = CGSizeMake(CELL_MESSAGE_WIDTH, 1000);

    // This is the method you should use in order to calculate the container size
    // Avoid using -sizeWithFont:constrainedToSize:lineBreakMode: as it is depracated in iOS7
    CGRect rect = [str boundingRectWithSize:maxSize
                                    options:NSStringDrawingUsesLineFragmentOrigin
                                 attributes:attributes
                                    context:NULL];


    return rect.size;
}

评论了一些行。正如您所看到的,大多数重要代码都落在了UITableVieCell的MyCell子类中。

另请注意{@ 1}}已弃用并使用-sizeWithFont:constrainedToSize:lineBreakMode:

答案 2 :(得分:0)

如果正在显示单元格而图像和文本不显示,则问题与textView的框架和imageView的框架有关。

您可以尝试在视图中勾选剪辑子视图(尤其是imageViews)并检查是否可以解决这个问题。

Clip Subviews

无论如何,我建议您使用autolayout然后定义视图的框架。

答案 3 :(得分:0)

最后,我能够自己解决这个问题。下面是一个详细的回答,突出了问题的原因和解决方案。

问题原因

  1. 项目[bgImageView(UIImageView)和messageText(UILabel)]是在Custom Cell类中定义的IBOutlets,并连接到Storyboard中的Cell。
  2. 每当我们尝试更改此类元素的框架(在故事板内定义)时,单元格不会更新,这是问题的根本原因。
  3. 解决方案

    为了解决这个问题,我从故事板中删除了元素,并在 -initWithCoder:中定义了它们。请注意,为Storyboard原型单元格的单元格(而不是 -initWithStyle:reuseIdentifier )调用此函数。

    initWithCoder:此方法将在自定义UITableViewCell类中定义(在我的例子中,类的名称是MyCell

    -(id)initWithCoder:(NSCoder *)aDecoder
    {
        self = [super initWithCoder:aDecoder];
        if(self)
        {
            //Settings sizes to zero as they will be changed in cellForRowAtIndexPath
            _bgImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
            [self.contentView addSubview:_bgImageView];
    
            _messageText = [[UILabel alloc] initWithFrame:CGRectZero];
            _messageText.backgroundColor = [UIColor clearColor];
            [_messageText sizeToFit];
            [_messageText setFont:[UIFont systemFontOfSize:12]];
            [_messageText setNumberOfLines:0];
            [self.contentView addSubview:_messageText];
    
       }
    
       return self;
    }
    

    heightForRowAtIndexPath *和* cellForRowAtIndexPath:也可供参考。

    <强> heightForRowAtIndexPath:

    -(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSString *message = .......;
    
        CGSize size = [self getSize:message];   //look below for getSize:
    
        size.height += 18 + 15;  //to cater for padding (top & bottom).
    
        return height;
    }
    

    <强>的cellForRowAtIndexPath:

    -(UITableViewCell *)tableView:(UITableView *)tblView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
         MyCell *cell = [tblView dequeueReusableCellWithIdentifier:@"msgCell"];
    
         NSString *message = ......;    
         CGSize size = [self getSize:message];   //look below for getSize:
    
         cell.messageText.text = message;
    
         [cell.messageText setFrame:CGRectMake(98, 13, size.width, size.height)];
         [cell.bgImageView setFrame:CGRectMake(79,5, CELL_MESSAGE_WIDTH+32, size.height+18)]; //write #define CELL_MESSAGE_WIDTH 200 at the top of the file (below include statements)
    
         [cell.bgImageView setImage:[[UIImage imageNamed:@"img.png"] stretchableImageWithLeftCapWidth:11 topCapHeight:23]];
    
         return cell;
    }
    

    <强> getMaxSize:

    -(CGSize)getSize:(NSString*)str
    {
        CGSize maxSize = CGSizeMake(CELL_MESSAGE_WIDTH, 1000);
        CGSize size = [str sizeWithFont:[UIFont systemFontOfSize:12] constrainedToSize:maxSize lineBreakMode:NSLineBreakByWordWrapping];
    
        return size;
    }