[英]cellForRowAtIndexPath: not called
我的应用程序有两种状态:登录和未登录,我有以下架构(大大简化):
- ViewController A 包含一个搜索框和一个表格视图。
- ViewController B 用于登录应用程序。
流程如下:
- 用户未登录;
- 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:
的断点永远不会被命中。
为什么会调用numberOfRowsInSection
但不会调用cellForRowAtIndexPath
一种有效情况是当表的大小或位置不需要显示任何行时。
例如,假设您有一个 20 像素高的表格,但是第一部分的标题是 30 高,并且您为标题返回了 nil(或者没有实现viewForHeaderInSection
)。 在这种情况下,不会显示任何行,并且看起来表格不存在。
我看到你在使用 IB。 表格的大小在 IB 中可能具有欺骗性,因为它假设页眉和页脚大小。 我会记录表格的框架,以便您了解应用程序运行时的位置(相对于它出现在 IB 中的位置)。 我还要确保在调用 reloadData之前手动调整表格框架的大小和位置。 这将解决未调用cellForRowAtIndexPath
这种有效情况。
检查numberOfSectionsInTableView
是否没有返回 0。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
我遇到了完全相同的问题,问题是我试图从另一个线程调用 reloadData: 。 解决方案是:
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
如果您像我一样使用不同的数据源,请确保保留数据源。 仅仅实例化将成为数据源的类并通过tableView.dataSource = myDataClass
分配它是不够的,因为 tableView 的 dataSource 属性很弱,并且会在 viewDidLoad 完成时释放。 所有其他方法都被我调用了——甚至,令人惊讶的是, heightForRowAtIndexPath
所以这花了我一些时间来调试。
// 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;
如果视图中的表视图与 Scrool 视图之类的内容发生冲突,则不会调用它。 您应该将 Storyboard 或 *.xib 文件中的视图分开。
// True
▼ View
► Table View
► Scrool View
► Constraints
// False
▼ View
► Scrool View
► Table View
► Constraints
我们有相同/相似的问题。 代码达到了numberOfSections
和numberOfRowsInSection
(它甚至返回了值)但无法达到cellForRowAt
。 当时,Storyboard 中的 Table View 只有右侧、左侧和顶部的约束,而没有底部的约束。 一旦我们在底部添加约束,它就像一个魅力。
因此,请检查您是否为表视图提供了所有需要的约束。
每个人都在谈论高度,但我在StackView
TableView
以领先对齐结束,宽度为 0。
确保使用Debug View Hierarchy
检查您的TableView
的大小是否正确。
如果您像我一样使用自动布局并将 tableview 添加到视图控制器的视图中,请确保在分配 table view 时添加了这一行。
tableView?.translatesAutoresizingMaskIntoConstraints = false
我这边的愚蠢错误。
我解决了这个问题,因为我添加了UITableView
子视图没有分配,所以它返回 nill 并且 tableview 没有调用cellForRowAtIndexPath
而是numberOfRowsInSection
被调用
我正在使用客户数据源,它已发布。 因为它是tableview的弱引用。
这令人尴尬和困惑,但这是我的解决方案。
我的代码:
_scanResultTable.delegate = self;
_scanResultTable.dataSource = self; // self's lifecycle was fine, wasn't getting released
[_scanResultTable reloadData];
所以奇怪的部分是:标识符 _scanResultTable 从未在我的代码中声明,在项目的任何地方。 我不知道这是如何编译的(我重新编译了几次)。
我的根本原因是我已将表输出链接到 ViewController 中的scanResultTable
,但将其称为 _scanResultTable。 一旦我开始像我应该使用的那样使用scanResultTable
,事情就清楚了。 这让我想知道objective-c是否有一些关于标识符中前导下划线的特殊之处......
编辑: 确实如此! 天哪,我迫不及待地不想再碰这种语言了。
浪费了几个小时,然后发现我的 tableview 在 stackview 中。 一旦我删除了堆栈视图,它就像一个魅力。 对我来说是 Xcode 11.3 。
我正在使用 ReactiveCocoa。 所以我为表视图创建了模型。 数据已准备好显示,因此numberOfRows
等。 但是我没有将 tableview 添加为 subview,因此没有调用cellForRowAtIndexPath
)))
- (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];
}
就我而言,我在StackView
有TableView
。 当我把它放在 StackView 之外时,它起作用了。
尝试手动插入新行而不是[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;
}
我通过检查 tableViewCell 标识符解决了同样的问题。 转到属性检查器并查看标识符部分。 大概是失踪了。 所以写单元格标识符。
同样的情况,但这是一个错误:
我在 ViewController 中包含了一个带有 2 个表视图的 Scrollview(设计要求),在滚动视图控制器中我以编程方式创建了 ViewControllers(包含 TableViews),我使用了一个弱变量来存储它,坏主意,因为它们是在年底发布的viewDidLoad 方法。
如果您没有看到您的 tableview 内容,请检查它是否已发布。
我的错误对我来说非常痛苦,因为除了 viewForCell 之外,所有方法(委托和数据源)都被调用了......
这里的答案都没有帮助我。
我正在以编程方式使用我的约束,但忘了写:
myTableView.translatesAutoresizingMaskIntoConstraints = false
确保您的约束是正确的,并且在构建时没有删除任何约束。
这可能太明显了,但在我的情况下,我正在以编程方式删除一个元素(标签),该元素是对表格顶部边距的引用,因此委托/源不是问题,而是表格的内容存在问题-大小/高度,这个冲突产生了一个奇怪的行为,调用 numberOfRowsInSection 而不是 cellForRowAt indexPath
您确定在用户登录并弹出 B 后,会调用 A 中的viewWillAppear
方法以执行刷新吗?
如果您将 B 显示为模态控制器,当您关闭它时,您将不会调用viewWillAppear
方法。
据我所知, viewWillAppear/viewDidAppear
(以及其他类似的)是 UINavigationController 在导航事件(push/pop viewcontrollers)的情况下生成的事件。 所以也许这就是为什么当你离开 A 并返回时你最终会刷新......这一切都取决于显示下一个视图控制器的方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.