为什么我的UITableView中的单元格显示为空?

3
我有一个有点奇怪的 UITableView 结构。基本上,我有一个由 ArticleCell 对象(UITableViewCell 的子类)组成的表格,每个 ArticleCell 由一个“前”视图和一个“后”视图组成。前视图显示用户看到的所有标签等内容,而后视图则在左右两侧具有两个图标。这个双视图的想法是让用户可以将顶部视图向右或向左滑动以快速选择选项(有点像 Reeder 中的效果)。
我在故事板中稍微实现了一下,但大部分都是在代码中完成的。我在故事板中所做的唯一一件事就是完成了 UITableViewController 的布局,并命名了原型单元格的标识符(标识符:“ArticleCell”)。
除了故事板之外,正如我所说的,一切都是在代码中完成的。我从 Core Data 获取单元格的信息,并通过将文章设置为单元格的 article 属性来构建单元格,然后将该文章设置为 CellFront UIViewarticle 属性。由于取决于单元格所持有的文章类型而存在两种单元格布局,在 CellFront 中它会检查它是哪种类型的单元格(一个名为 isUserAddedText 的属性)并相应地创建布局。
但正如我所说的,当应用程序加载时没有任何内容显示出来,所有单元格都会加载,并且我可以点击它们以查看其内容,但单元格本身是空白的。
相关代码如下:
单元格数据源:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    ArticleInfo *articleInfo = [self.fetchedResultsController objectAtIndexPath:indexPath];

    static NSString *CellIdentifier = @"ArticleCell";

    ArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[ArticleCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    cell.article = articleInfo;

    return cell;
}

ArticleCell.m 文件中,我重写了 article 的 set 方法,这样当上面的数据源方法调用它时,它可以同时设置视图的 article 属性。
- (void)setArticle:(ArticleInfo *)article {
    _article = article;

    self.cellFront.article = article;
}

我还在ArticleCell.m文件中创建了CellFrontCellBackUIView

- (void)awakeFromNib {
    [super awakeFromNib];

    self.cellBack = [[CellBack alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 80)];
    [self.contentView addSubview:self.cellBack];

    self.cellFront = [[CellFront alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 80)];
    [self.contentView addSubview:self.cellFront];
}

CellFront.m在其initWithFrame:方法中调用以下方法,根据文章类型设置标签并将它们添加到子视图中。

- (void)addControlsToView {
    if ([self.article.isUserAddedText isEqualToNumber:@YES]) {
        UILabel *preview = [[UILabel alloc] initWithFrame:CGRectMake(20, 5, 280, 70)];
        preview.text = self.article.preview;
        preview.numberOfLines = 4;
        preview.font = [UIFont systemFontOfSize:16.0f];
        preview.textColor = [UIColor blackColor];
        preview.backgroundColor = [UIColor clearColor];
        [self addSubview:preview];
    }
    else {
        UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 280, 20)];
        title.text = self.article.title;
        title.font = [UIFont boldSystemFontOfSize:18.0f];
        title.textColor = [UIColor blackColor];
        title.backgroundColor = [UIColor clearColor];
        [self addSubview:title];

        UILabel *URL = [[UILabel alloc] initWithFrame:CGRectMake(20, 35, 280, 20)];
        URL.text = self.article.url;
        URL.font = [UIFont systemFontOfSize:16.0f];
        URL.textColor = [UIColor blackColor];
        URL.backgroundColor = [UIColor clearColor];
        [self addSubview:URL];

        UILabel *preview = [[UILabel alloc] initWithFrame:CGRectMake(20, 60, 280, 40)];
        preview.text = self.article.preview;
        preview.numberOfLines = 2;
        preview.font = [UIFont systemFontOfSize:16.0f];
        preview.textColor = [UIColor grayColor];
        preview.backgroundColor = [UIColor clearColor];
        [self addSubview:preview];
    }
}

这是我认为应该包含的所有相关信息。为什么所有单元格都显示为空白?

在Storyboard中,你是否将原型表视图单元格的自定义类设置为“ArticleCell”? - Mike Mertsock
1个回答

2
如果你没有使用故事板或NIB来定义你的视图,awakeFromNib:将不会被调用。
这里有一些文档
你应该尝试重写initWithStyle:reuseIdentifier:而不是awakeFromNib:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self != nil) {
        // DO STUFF
    }

    return self;
}

如果您正在尝试使用故事板,则您未正确地出列单元格,请替换以下内容:
ArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {
    cell = [[ArticleCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

使用:

ArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

如果队列中没有单元格,此方法将从故事板初始化新的单元格。你之前使用的方法不会这样做。这意味着有时候单元格将等于nil,然后你使用initWithStyle:reuseIdentifier:方法初始化一个新的单元格,这将不会调用awakeFromNib,因为你没有从NIB中解码它。

这是关于此方法的文档链接


附加信息

你也看不到单元格中的数据,因为你在同一个代码块中设置标签文本值和初始化视图。基本上,你需要这样做:

...
preview.text = self.article.preview;
...

...在每次单元格被重用时,都会执行addControlsToView方法的这一部分,并且UILabel的初始化只会执行一次。我建议将上述代码移动到CellFront类中文章属性的setter方法中。例如,首先为标签声明一些属性。

@property (nonatomic, strong) UILabel *preview1Label;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *URLLabel;
@property (nonatomic, strong) UILabel *preview2Label;

然后像这样初始化控件

- (void)initControls {
    self.preview1 = [[UILabel alloc] initWithFrame:CGRectMake(20, 5, 280, 70)];
    self.preview1.text = self.article.preview;
    self.preview1.numberOfLines = 4;
    self.preview1.font = [UIFont systemFontOfSize:16.0f];
    self.preview1.textColor = [UIColor blackColor];
    self.preview1.backgroundColor = [UIColor clearColor];
    [self addSubview:self.preview1];

    self.title = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 280, 20)];
    self.title.text = self.article.title;
    self.title.font = [UIFont boldSystemFontOfSize:18.0f];
    self.title.textColor = [UIColor blackColor];
    self.title.backgroundColor = [UIColor clearColor];
    [self addSubview:self.title];

    self.URL = [[UILabel alloc] initWithFrame:CGRectMake(20, 35, 280, 20)];
    self.URL.text = self.article.url;
    self.URL.font = [UIFont systemFontOfSize:16.0f];
    self.URL.textColor = [UIColor blackColor];
    self.URL.backgroundColor = [UIColor clearColor];
    [self addSubview:self.URL];

    self.preview2 = [[UILabel alloc] initWithFrame:CGRectMake(20, 60, 280, 40)];
    self.preview2.text = self.article.preview;
    self.preview2.numberOfLines = 2;
    self.preview2.font = [UIFont systemFontOfSize:16.0f];
    self.preview2.textColor = [UIColor grayColor];
    self.preview2.backgroundColor = [UIColor clearColor];
    [self addSubview:self.preview2];
}

然后像这样设置控件,可能是从文章属性的setter中完成的。

- (void)setControls {
    if ([self.article.isUserAddedText isEqualToNumber:@YES]) {
        self.preview1.hidden = NO;
        self.preview1.text = self.article.preview;
        self.title.hidden = YES;
        self.title.text = nil;
        self.URL.hidden = YES;
        self.URL.text = nil;
        self.preview2.hidden = YES;
        self.preview2.text = nil;
    }
    else {
        self.preview1.hidden = YES;
        self.preview1.text = nil;
        self.title.hidden = NO;
        self.title.text = self.article.title;
        self.URL.hidden = NO;
        self.URL.text = self.article.url;
        self.preview2.hidden = NO;
        self.preview2.text = self.article.preview;
    }
}

你是否有一个故事板或NIB以及你发布的代码? - Michael Reneer
是的,请看第二段。 - Doug Smith
抱歉,我错过了那个细节,并且假设你使用的是dequeue方法并且无论如何都在代码中创建所有对象,因此你没有使用storyboard。我已经编辑了我的回答。 - Michael Reneer
那似乎很不幸地什么也没做。 - Doug Smith
如果您可以发送给我项目或源代码的链接,我会查看一下。 - Michael Reneer
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接