【问题标题】:UITableView skips one indexPath between every one of custom UITableViewCell, disappears when scrollingUITableView 在每个自定义 UITableViewCell 之间跳过一个 indexPath,滚动时消失
【发布时间】:2014-03-31 11:08:42
【问题描述】:

图片中的问题:

基本上,我的表格视图在彼此之间添加了一个空单元格,我不知道为什么。我已经尝试在cellForRowAtIndexPath:willDisplayCell:forRowAtIndexPath:didSelectRowAtIndexPath: 中放置一个NSLog 语句,并且每个单元格的indexPath 中的数据源是正确的。只是显示的单元格在中间跳过,我不明白为什么。

我的视图控制器和表格视图单元子类也很简单。代码如下:

PrivateMessagesViewController.m

static NSString * const kCellIdentifier = @"kCellIdentifier";

@interface PrivateMessagesViewController () <UITableViewDataSource, UITableViewDelegate>

@property (strong, nonatomic) NSMutableArray *messages;
@property (strong, nonatomic) SCPFInboxQuery *query;
@property (nonatomic) BOOL hasAlreadyFetchedBefore;

@property (strong, nonatomic) UITableView *tableView;

// This is a custom view that either shows a loading animation,
// a "No Results Found" label, or an error message with a Retry button
// at the center of the view of a view controller.
@property (strong, nonatomic) SCPCenterView *centerView;

@end

@implementation PrivateMessagesViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.title = @"Private Messages";

    self.messages = [NSMutableArray array];
    self.query = [[SCPFInboxQuery alloc] init];

    self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, [UIScreen mainScreen].bounds.size.height - 113) style:UITableViewStylePlain];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
    [self.tableView registerClass:[SCPPrivateMessageListCell class] forCellReuseIdentifier:kCellIdentifier];
    self.tableView.alpha = 0; // The table view starts out invisible.
    [self.view addSubview:self.tableView];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if (!self.hasAlreadyFetchedBefore) {
        [self.view addSubview:self.centerView];
        [self.centerView showLoadingView];

        __weak PrivateMessagesViewController *weakSelf = self;
        [self.query runInBackgroundWithCompletion:^(NSArray *messages, NSError *error) {
            PrivateMessagesViewController *innerSelf = weakSelf;

            // If there is an error, handle it.
            if (error) {
                // ...
                return;
            }

            // If there weren't any messages before and none were found,
            // the user has no messages in the inbox.
            if (!innerSelf.hasAlreadyFetchedBefore && messages.count == 0) {
                [innerSelf.centerView showNoResultsLabel];
            }

            else {
                if (!innerSelf.hasAlreadyFetchedBefore) {
                    [innerSelf.centerView fadeOutAndRemoveFromSuperview];
                    innerSelf.tableView.alpha = 1;
                } else {
                }
                [innerSelf.messages addObjectsFromArray:messages];
                [innerSelf.tableView reloadData];
            }

            innerSelf.hasAlreadyFetchedBefore = YES;
        }];
    }
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.messages.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    SCPPrivateMessageListCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
    SCPFMessage *message = self.messages[indexPath.row];
    cell.message = message;
    return cell;
}

#pragma mark - Table view delegate

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [SCPPrivateMessageListCell heightForMessage:self.messages[indexPath.row]];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    SCPPrivateMessageListCell *theCell = (SCPPrivateMessageListCell *)cell;
    NSLog(@"Message at %d: %@", indexPath.row, theCell.message.rawData);
}

#pragma mark - Getters

- (SCPCenterView *)centerView
{
    if (!_centerView) {
        _centerView = [[SCPCenterView alloc] initWithParent:self.view];
        _centerView.noResultsText = @"You don't have any private messages yet.";
    }
    return _centerView;
}

@end

SCPPrivateMessageListCell.m

static const CGFloat kInnerMargin = 10;
static const CGFloat kSpaceBetweenImageAndRightLabel = 10;
static const CGFloat kImageViewSize = 60;
static const CGFloat kRightLabelX = kInnerMargin + kImageViewSize + kSpaceBetweenImageAndRightLabel;
static const CGFloat kMaxRightLabelWidth = 320 - (kRightLabelX + kInnerMargin);

@interface SCPPrivateMessageListCell ()

@property (strong, nonatomic) UIImageView *thumbnailImageView;
@property (strong, nonatomic) UILabel *dateLabel;
@property (strong, nonatomic) UILabel *senderLabel;
@property (strong, nonatomic) UILabel *subjectLabel;
@property (strong, nonatomic) UILabel *summaryLabel;

@end

@implementation SCPPrivateMessageListCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
    if (self) {
        _thumbnailImageView = [[UIImageView alloc] init];
        _thumbnailImageView.contentMode = UIViewContentModeScaleAspectFill;
        _thumbnailImageView.layer.cornerRadius = kImageViewSize / 2;
        _thumbnailImageView.clipsToBounds = YES;

        _dateLabel = [[UILabel alloc] init];
        _dateLabel.font = [UIFont systemFontOfSize:10];
        _dateLabel.textAlignment = NSTextAlignmentCenter;
        _dateLabel.numberOfLines = 1;
        _dateLabel.lineBreakMode = NSLineBreakByTruncatingTail;

        _senderLabel = [SCPPrivateMessageListCell senderLabel];
        _subjectLabel = [SCPPrivateMessageListCell subjectLabel];
        _summaryLabel = [SCPPrivateMessageListCell summaryLabel];

        [self.contentView addSubview:_thumbnailImageView];
        [self.contentView addSubview:_dateLabel];
        [self.contentView addSubview:_senderLabel];
        [self.contentView addSubview:_subjectLabel];
        [self.contentView addSubview:_summaryLabel];
    }
    return self;
}

- (void)setMessage:(SCPFMessage *)message
{
    _message = message;

    [self.thumbnailImageView setImageWithURL:message.thumbnailURL];
    self.dateLabel.text = message.dateSent;
    self.senderLabel.text = message.nameOfSender;
    self.subjectLabel.text = message.subject;
    self.summaryLabel.text = message.summary;

    [self setNeedsLayout];
}

- (void)layoutSubviews
{
    self.thumbnailImageView.frame = CGRectMake(kInnerMargin, kInnerMargin, kImageViewSize, kImageViewSize);

    [self.dateLabel sizeToFitWidth:kImageViewSize];
    self.dateLabel.frame = CGRectMake(kInnerMargin, kInnerMargin + kImageViewSize, kImageViewSize, self.dateLabel.frame.size.height);

    [self.senderLabel sizeToFitWidth:kMaxRightLabelWidth];
    self.senderLabel.frame = CGRectMake(kRightLabelX, kInnerMargin, kMaxRightLabelWidth, self.senderLabel.frame.size.height);

    CGFloat subjectLabelY = self.senderLabel.frame.origin.y + self.senderLabel.frame.size.height;
    [self.subjectLabel sizeToFitWidth:kMaxRightLabelWidth];
    self.subjectLabel.frame = CGRectMake(kRightLabelX, subjectLabelY, kMaxRightLabelWidth, self.subjectLabel.frame.size.height);

    CGFloat summaryLabelY = self.subjectLabel.frame.origin.y + self.subjectLabel.frame.size.height;
    [self.summaryLabel sizeToFitWidth:kMaxRightLabelWidth];
    self.summaryLabel.frame = CGRectMake(kRightLabelX, summaryLabelY, kMaxRightLabelWidth, self.summaryLabel.frame.size.height);

    CGFloat cellHeight = [SCPPrivateMessageListCell heightForMessage:self.message];
    self.contentView.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, cellHeight);
    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, cellHeight);
}

#pragma mark - Class methods

+ (UILabel *)senderLabel
{
    UILabel *label = [[UILabel alloc] init];
    label.font = [UIFont boldSystemFontOfSize:17];
    label.textColor = [UIColor colorFromHex:0x0076be];
    label.numberOfLines = 1;
    label.lineBreakMode = NSLineBreakByTruncatingTail;
    return label;
}

+ (UILabel *)subjectLabel
{
    UILabel *label = [[UILabel alloc] init];
    label.font = [UIFont systemFontOfSize:14];
    label.numberOfLines = 1;
    label.lineBreakMode = NSLineBreakByTruncatingTail;
    return label;
}

+ (UILabel *)summaryLabel
{
    UILabel *label = [[UILabel alloc] init];
    label.font = [UIFont systemFontOfSize:12];
    label.textColor = [UIColor grayColor];
    label.numberOfLines = 3;
    label.lineBreakMode = NSLineBreakByTruncatingTail;
    return label;
}

+ (CGFloat)heightForMessage:(SCPFMessage *)message
{
    CGFloat height = kInnerMargin;

    UILabel *senderLabel = [SCPPrivateMessageListCell senderLabel];
    senderLabel.text = message.nameOfSender;
    [senderLabel sizeToFitWidth:kMaxRightLabelWidth];
    height += senderLabel.frame.size.height;

    UILabel *subjectLabel = [SCPPrivateMessageListCell subjectLabel];
    subjectLabel.text = message.subject;
    [subjectLabel sizeToFitWidth:kMaxRightLabelWidth];
    height += subjectLabel.frame.size.height;

    UILabel *summaryLabel = [SCPPrivateMessageListCell summaryLabel];
    summaryLabel.text = message.summary;
    [summaryLabel sizeToFitWidth:kMaxRightLabelWidth];
    height += summaryLabel.frame.size.height;

    height += kInnerMargin;

    return height;
}

@end

那里。我没有做任何不标准的事情。当我滚动时,单元格的子视图也会消失,但是当我将它们滚动回来时,内容会显示出来,仍然有一个跳过的空单元格。有人知道为什么会这样吗?

【问题讨论】:

  • 我不确定,但如果使用重用标识符的初始化失败,您可能从未初始化单元格。

标签: ios iphone objective-c cocoa-touch uitableview


【解决方案1】:

问题出在我的表格视图单元格的layoutSubviews

self.contentView.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, cellHeight);

应该是这样的:

self.contentView.frame = CGRectMake(self.contentView.frame.origin.x, self.contentView.frame.origin.y, self.contentView.frame.size.width, cellHeight);

我是通过在 init 方法内部为 self.backgroundColorself.contentView.backgroundColor 设置不同的颜色发现的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    相关资源
    最近更新 更多