cellForRowAtIndexPath返回nil。

17

我试图从一个表视图中获取特定的单元格,以便更改它的标签并停止活动指示器。

我遇到的问题是cellForRowAtIndexPath返回nil。

我的表视图只有1行。

代码:

- (id) initWithNibName: (NSString*) nibNameOrNil bundle: (NSBundle*) nibBundleOrNil
{
    self = [super initWithNibName: nibNameOrNil bundle: nibBundleOrNil];

    if (self) 
    {
        numberOfRows = 1;
    }

    return self;
}

- (NSInteger) tableView: (UITableView*) tableView numberOfRowsInSection: (NSInteger) section
{
    return numberOfRows;
}

-(void) stopCellIndicator
{

    LiveUserFeedCell* cell = (LiveUserFeedCell*)[self.liveFeed cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];  
    [cell.activityIndicator stopAnimating];
    cell.middleLabel.text = @"N/a";
}

- (UITableViewCell*) tableView: (UITableView*) tableView cellForRowAtIndexPath: (NSIndexPath*) indexPath
{
    static NSString *CellIdentifier = @"UserFeedCell";


    LiveUserFeedCell *cell = (LiveUserFeedCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"LiveUserFeedCell" owner:self options:nil];
        cell = (LiveUserFeedCell *)[nib objectAtIndex:0];
    }

    [cell.imgView setImage:[TUNinePatchCache imageOfSize:cell.imgView.frame.size forNinePatchNamed:@"bg_home_newsfeed_normal"]];


    if (shouldDisplayLoading == NO)
    {
        NSArray* songs = homeScreen.recentPlaybacks.songs;
        TWSong* song = [songs objectAtIndex:index];
        cell.middleLabel.text = @"";
        [cell.activityIndicator stopAnimating];

        UIFont *font = [UIFont fontWithName:@"Trebuchet MS" size:14];                       

        NSString* kText =[NSString stringWithFormat:@"<b>%@</b> is listening to %@ by %@",song.user,song.title,song.artist];

        for(int i = 14; i > 0; i=i-1)
        {
            // Set the new font size.
            font = [font fontWithSize:i];
            // You can log the size you're trying: NSLog(@"Trying size: %u", i);

            /* This step is important: We make a constraint box 
             using only the fixed WIDTH of the UILabel. The height will
             be checked later. */ 
            CGSize constraintSize = CGSizeMake(cell.isWatching.frame.size.width, MAXFLOAT);

            // This step checks how tall the label would be with the desired font.
            CGSize labelSize = [kText sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

            /* Here is where you use the height requirement!
             Set the value in the if statement to the height of your UILabel
             If the label fits into your required height, it will break the loop
             and use that font size. */
            if(labelSize.height <= cell.isWatching.frame.size.height)
                break;
        }



        cell.isWatching.font = font;
        cell.isWatching.text = [TTStyledText textFromXHTML:kText lineBreaks:YES URLs:YES];
        cell.isWatching.textAlignment = UITextAlignmentCenter;

        ++index;
        if (index == [songs count])
            index=0;

    }
    else
    {       
        [cell.activityIndicator startAnimating];
    }

    return cell;
}

但是,如果我像这样做,我确实会得到一个有效的单元格:

NSArray *indexPaths = [NSArray arrayWithObjects: 
                       [NSIndexPath indexPathForRow:0 inSection:0],
                       nil];

numberOfRows = 0;
[self.liveFeed deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft];


numberOfRows = 1;
[self.liveFeed insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];

LiveUserFeedCell* cell = (LiveUserFeedCell*)[self.liveFeed cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];  
[cell.activityIndicator stopAnimating];
cell.middleLabel.text = @"N/a";

有什么办法可以解决这个问题吗?(也许默认的第一个单元格不在第0行第0节中?)


我看不到你在哪里重写了 cellForRowAtIndex。只要你没有这样做,就不会有任何单元格。 - Krumelur
添加了更多的代码...现在看一下。谢谢。 - Idan
7个回答

39
值得一提的是,当cell不可见时,cellForRowAtIndexPath: 也会返回nil。这在多线程情况下尤其容易出现问题...

2
你如何处理这个问题?当另一个视图控制器处于活动状态时,我需要对该单元格进行引用。 - n00bProgrammer
“另一个VC”是什么意思? 另一个活动的VC(B)不会影响不同VC(A)中的单元格。这指的是1个VC内的单元格,并且:如果单元格未激活,则无法引用它,因为它不存在。 VC回收一些单元格对象并重复使用它们。 - Andres Canella
在需要的地方保留单元格的副本并使用它,这样做有意义吗? - Kiran Ruth R
1
不需要保留对单元格对象的直接引用,因为单元格对象会被Table对象不断重复使用和管理。单元格对象在任何给定时间都代表数据源中的不同项。如果单元格不可见,则无需对其进行任何操作,因为它不存在。通常尝试访问不在视图中的单元格会导致错误。 - Andres Canella
1
谢谢,这是非常重要的信息,救了我的一天。 - Zoltan Vinkler

15

我一直在遇到cellForRowAtIndexPath返回空值的问题,而对我来说导致这个问题的原因是我在UITableView尚未完全初始化和填充的方法中调用了它。一旦我将我的调用移动到-(void)viewDidAppear:(BOOL)animated中,那么我的单元格就会正确返回。


5
我遇到了同样的问题,cellForRowAtIndexPath返回nil,而原因很傻。在tableView:cellForRowAtIndexPath:中,我调用了一个方法,该方法又调用了一个方法,该方法调用了[self.tableView cellForRowAtIndexPath:indexPath]。 (重复使用现有代码,并将一些逻辑下移。)
事实证明,在cellForRowAtIndexPath中,cell尚不可用以返回。您可以在tableView:cellForRowAtIndexPath:中进行所有业务修改或将*cell传递。

3
我遇到了和你类似的问题,但是我通过调用“super”函数而不是self.tableView来解决了这个问题。我不知道为什么,但至少它起作用了。也许你可以试一下。
[super tableView:self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];

顺便提一下,我的表是静态表,可能与你的情况不同。 - Christopher
根据苹果公司的说法,从iOS 11开始,您必须避免使用tableView: cellForRowAtIndexPath:方法,否则它会导致应用程序崩溃。 - Vineet Ashtekar
@VineetAshtekar 什么?我无法在任何地方找到这些信息。你能展示任何证明这些信息的参考资料吗? - Nat
1
嗨@VineetAshtekar,如果您能提供一个参考资料会更好。此外,我的答案是在2015年发布的,当时iOS 11还没有发布。您能否建议一下我的答案是否已经过时,以便我进行编辑? - Christopher

1

你已经解决了这个问题,虽然我也遇到了类似的情况,但我做的是向你展示:

NSArray *cells = [contactsTable visibleCells];

    UITableViewCell *cell = nil;
    NSIndexPath *path = [param objectAtIndex:1];
    for (UITableViewCell *aCell in cells) {
        NSIndexPath *aPath = [contactsTable indexPathForCell:aCell];

        if ([aPath isEqual:path]) {
            cell = aCell;
        }
    }

经过数小时的试错,这种奇怪的方法效果很好。


0

尝试使用:

[self.livFeed beginUpdates];   
LiveUserFeedCell* cell = (LiveUserFeedCell*)[self.liveFeed cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];  
[cell.activityIndicator stopAnimating];
cell.middleLabel.text = @"N/a";
[self.liveFeed endUpdates];

苹果UITableView文档


在 beginUpdates 和 endUpdates 中获取 cellForRowAtIndexPath 是如何帮助确保单元格不为空的? - Kiran Ruth R

-6

显然问题是当我查询单元格时,tableView尚未配置好。


4
你说的“configured”,是什么意思?如何进行配置? - Carlo
2
将后面的两个杠杆移至竖直位置。然后按下启动按钮,很简单。 - Jonny

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