cellForRowAtIndexPath:不被调用


72

我的应用程序具有两种状态:已登录和未登录,并且具有以下架构(大大简化了):
-ViewController A,其中包含一个搜索框和一个表视图。
-用于登录应用程序的ViewControllerB。

流程如下:
-用户未登录;
-A被压入堆栈。在“viewWillAppear我检查用户是否已登录”中,如果是,则正在发出异步网络请求,完成后,该表将从网络中装入数据。但是,由于此时用户尚未登录,因此表视图为空;因此,表视图为空。
-用户点击搜索框;因为他尚未登录,所以B被推送(在确认之后);
-他成功登录B,然后按一个按钮,弹出B并再次显示A;
-此时,由于他已登录,因此viewWillAppear我发出了异步请求;
-完成后,我调用reloadData表格视图。

我注意到的是 numberOfRowsInSection:被调用并且返回正确的结果,但是cellForRowAtIndexPath:之后没有被调用,并且该表仍然为空。

我检查了 reloadData在主线程上被调用。

知道会是什么吗?因为它让我发疯!

谢谢,
S。

编辑:这是A中的异步代码viewWillAppear

if ([User isLoggedIn]) {
    [self.asyncRequest fetchDataWithCompletionHandler:^(id response, NSError *error) {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        if (error) {
            [Utils displayError:error];
        } else {
            self.array = response;

            self.isLoaded = YES;
            [self.tableView reloadData];
            [self.tableView setContentOffset:CGPointMake(0.0f, 0.0f) animated:NO];
        }
    }];
}

我检查了异步请求是否成功完成,并且response包含正确的数据(这是用于支持的数组UITableView)。

之后reloadData,我在其中放置了一个断点,tableView:numberOfRowsInSection:并在此停了下来,并在中返回了正确数量的元素array。但是,此后tableView:cellForRowAtIndexPath:再也不会遇到断点了。


正确的方法选择器tableView:cellForRowAtIndexPath:不是cellForRowAtIndexPath:
Ole Begemann

如果numberOfRowsInSection:返回正确的数据,我认为设置委托和数据源可能存在问题。你可以发布一些代码吗?
Shri

是的,我知道,就是那个。我在这里粘贴了简短的版本。
Stelian Iancu

委托和数据源在Interface Builder中设置为文件的所有者(即A)。
Stelian Iancu

此外,还有一点:此后效果很好,即,如果我登录后从A切换到A,然后又回到A,表将正确填充。只有当我从B返回时,它才起作用。
Stelian Iancu

Answers:


272

为什么numberOfRowsInSection会调用一个有效的方案,但是cellForRowAtIndexPath不会是表的大小或位置不需要显示任何行时。

例如,假设您的表高20像素,但第一部分的表头高30像素,并且表头返回nil(或未实现viewForHeaderInSection)。在这种情况下,将不会显示任何行,并且看起来好像表格不存在。

我看到您正在使用IB。表的大小在IB中可能具有欺骗性,因为它假定页眉和页脚的大小。我将记录表格的框架,以便您了解运行应用程序时的位置(相对于IB中出现的位置)。我还要确保调用reloadData之前手动调整表框架的大小和位置。这将解决cellForRowAtIndexPath未调用的有效情况。


70
这个家伙知道他在说什么。
akaru 2012年

这里的答案很棒,@ joel给出了很好的解释。实际上,我遇到了类似的问题,并且花了几乎一天的时间进行调试。就我而言,cellForRowAtIndexPath函数将不会被调用。有了这个答案,我发现AutoLayout将表格的高度计算为0。这就是根本原因,App决定根本不渲染单元格。
关冠

2
我讨厌让Xcode提出视图约束。我的表视图由于建议的$#!tty约束而从未出现。更改了约束,一切运行正常。
RyJ 2014年

我对此略有不同。我在不使用自动布局的情况下将UITavleView与IB一起放置。表格视图的框架设置为自动拉伸到单元格的高度。在.m文件中,我设置单元格框架的高度和表格视图框架的高度。XCode第一次显示表视图时忽略了我的代码集框架,但第二次尊重setFrame调用。当我在Y轴上禁用自动拉伸时,我的问题消失了,并且setFrame方法按预期工作。XCode约束有时很痛苦。感谢您的回答!
JasonD 2014年

标头如何为30,但随后又返回nil了?您是在谈论某人是否已实施heightForHeaderInSection并且他将返回30,但随后viewForHeaderInSection又返回了nil吗?
亲爱的

44

检查并确保numberOfSectionsInTableView不返回0。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

2
我遇到了与原作者相同的问题。如您的答案所示,此方法返回1,并被调用...而未调用cellForRowAtIndexPath。数据源和委托通过Interface Builder设置为文件的所有者。我什至尝试通过代码(tableView.delegate = self)设置它,但仍然没有被调用。只是以为我会贡献这些因素,因为作者尚未接受答案,但您似乎走对了。希望有人能弄清楚!
丹尼

6
根据苹果公司的说法,“默认值为1”。不需要此方法。
Peter DeWeese

4
回答这个问题时绝对需要。
彼得·凯利

我可以确认此方法返回0并引起麻烦。我已经实现了它,以便在我的表视图控制器中返回1,并且所有问题都已修复。
CanPoyrazoğlu17年

它为我返回了3。
ScottyBlades


16

如果像我一样使用其他数据源,请确保保留数据源。仅实例化将成为dataSource的类并通过进行分配tableView.dataSource = myDataClass是不够的,因为tableView的dataSource属性很弱,并且将在viewDidLoad完成时释放。所有其他方法都被我召唤了,甚至令人惊讶,heightForRowAtIndexPath所以这花了我一些时间进行调试。


感谢分享。对于heightForRowAtIndexPath,正是在委托中才是为什么要调用它的原因。
Y.Bonafons

这是如此有效
king_T

12
// For others showing up on this questions via Google, etc.
// Check and make sure you've set the table view's data source and delegate.
self.tableView.dataSource = self;
self.tableView.delegate = self;

12

如果视图内的表视图与Scrool视图之类的内容冲突,则不会调用该视图。您应该在故事板或* .xib文件中分离视图。

// TrueView
        ► Table View
        ► Scrool View
        ► Constraints

// FalseView
        ► Scrool View
            ► Table View
        ► Constraints

5

我们有相同/相似的问题。代码达到numberOfSectionsnumberOfRowsInSection(甚至返回值),但不能达到cellForRowAt。当时,情节提要中的“表视图”仅对右侧,左侧和顶部具有约束,而对底部没有约束。将约束添加到底部后,它就像是一种魅力。

因此,请检查您是否为表视图提供了所有必需的约束。


4

每个人都在谈论高度,但是我TableViewStackView领先优势最终以0宽度告终。

确保使用检查您TableView的尺寸是否正确Debug View Hierarchy


那您的解决方案是什么?我的是在stackView中,但是我仍然看不到调试器
Honey

@Honey,您可能希望将其高度约束设置为常量并禁用滚动。
Yaroslav

实际上,我只是从stackview中删除了它,仍然没有什么不同。其他方法受到打击,但没有受到打击cellforrowatindexpath。仅供参考,这是UIView中的tableView ...
Honey

@Honey不确定如何帮助您提供大量信息,请确保在numberOfRows中不返回0 :)
Yaroslav

相同的问题,我在堆栈视图中使用了表格视图,而不是cellForRowAt indexPath不起作用
Harshil Kotecha

3

我解决了这个问题,因为UITableView未分配添加了子视图的子视图,因此它返回nill,而tableview没有调用cellForRowAtIndexPath而是numberOfRowsInSection被调用


3

如果您正在使用像我这样的自动布局并将tableview添加到视图控制器的视图中,请确保在分配表视图时已添加此行。

tableView?.translatesAutoresizingMaskIntoConstraints = false

我这边愚蠢的错误。


救了我几个小时哈哈。谢谢
Roi Mulia

2

我正在使用客户数据源,该数据源已发布。因为它是tableview的弱引用。


2

这令人尴尬和困惑,但这是我的解决办法。

我的代码:

_scanResultTable.delegate = self;
_scanResultTable.dataSource = self; // self's lifecycle was fine, wasn't getting released
[_scanResultTable reloadData];

因此,很奇怪的部分是:标识符_scanResultTable从未在我的代码中的项目中任何地方声明过。我不知道如何编译(并且我重新编译了好几次)。

我的根本原因是我已经将表输出链接到scanResultTableViewController中,但是将其称为_scanResultTable。一旦开始使用scanResultTable应有的功能,一切就变好了。这让我想知道Objective-C是否在标识符的下划线前有特殊之处...

编辑:确实如此!上帝,我迫不及待想再也不要碰这种语言。


我也解决了这个问题。<3
Pepper

2

浪费了几个小时,然后发现我的表视图在堆栈视图内。一旦我删除了stackview,它就像一个魅力。对我来说,它是Xcode 11.3。


1
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Make sure self.data isn't nil!
    // If it is, you'll always return 0 and therefore
    // cellForRowAtIndexPath will never get called.
    return [self.data count]; 
}

1

我正在使用ReactiveCocoa。因此,我为表视图创建了模型。准备显示数据,以此类推numberOfRows。但是我还没有将tableview添加为子视图,因此cellForRowAtIndexPath没有被调用)))


1

就我而言,我的TableView内部是StackView。当我将其放在StackView之外时,它可以工作。


0

您确定在用户登录并弹出B之后,viewWillAppear调用A中的方法以执行刷新吗?

如果将B显示为模态控制器,则将其关闭时,您将没有 viewWillAppear调用方法。

据我所知,viewWillAppear/viewDidAppear(以及其他类似的)事件是由UINavigationController在导航事件(推/弹出视图控制器)的情况下生成的事件。所以也许这就是为什么当您离开A并返回时最终得到刷新的原因……这完全取决于显示下一个ViewController的方式。


是的,我确定,我已经在代码中放置了断点,并且看到它们被击中了。一切正常,直到应调用tableView:cellForRowAtIndexPath:为止。
Stelian Iancu

那我就没主意了。也许如果您发布更多代码,我们可能会发现可能的错误。但是肯定是可疑的。
安德烈·斯坦尼斯库

0

尝试手动插入新行,而不是[self.tableView reloadData]

[self.tableView beginUpdates];
    for (int i = 0; i < responseArray.count; i++) {
        _rowsNumber += 1;
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
        [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom];
    }
[self.tableView endUpdates];

在dataSource方法中,返回值递增int _rowsNumber

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

0

我通过检查tableViewCell标识符解决了相同的问题。转到属性İnspector,然后查看“标识符”部分。可能丢失了。所以写单元格标识符。


0

这里的情况相同,但这是一个错误:

我在ViewController中包含了一个带有2个tableViews的Scrollview(设计要求),在scrollview控制器中,我以编程方式创建了ViewControllers(包含TableViews),并且我使用了一个弱var来存储它,这是一个不好的主意,因为它们是在viewDidLoad方法。

如果看不到tableview内容,请检查它是否已发布。

我的错误对我来说是非常痛苦的,因为除viewForCell以外的所有方法(委托和数据源)都被调用了。


0

我有相同的问题,我在StackView和Table View内禁用了Table View并禁用了滚动和设置高度限制,但是在那之后

tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

无法正常工作时,请停止调用此方法,Data Source并且Delegate正确设置。

如果您与“解决方案”设置存在相同的问题,请设置Table View底部,前导,尾随约束

在此处输入图片说明


0

这里的答案都没有帮助我。

我正在以编程方式执行约束,但忘了写:

myTableView.translatesAutoresizingMaskIntoConstraints = false

0

确保您的约束是正确的,并且在构建时不会删除任何约束。


0

这也许太明显了,但是在我的情况下,我正在以编程方式删除一个元素(标签),该元素是对我的表格的上边距的引用,因此这与委托/源无关,但是表格的内容存在一些问题,大小/高度,此冲突创建了一个怪异的行为,调用numberOfRowsInSection但未调用cellForRowAt indexPath

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.