简体   繁体   English

cellForRowAtIndexPath:未调用

[英]cellForRowAtIndexPath: not called

My app has two states: logged in and not logged in, and I have the following architecture (vastly simplified):我的应用程序有两种状态:登录和未登录,我有以下架构(大大简化):
- ViewController A which contains a search box and a table view. - ViewController A 包含一个搜索框和一个表格视图。
- ViewController B which is used for logging in the app. - ViewController B 用于登录应用程序。

The flow is the following:流程如下:
- the user is not logged in; - 用户未登录;
- A is pushed on the stack. - A 被压入堆栈。 In viewWillAppear I check if the user is logged in and if yes, an async network request is being made and, once that is done, the table is loaded with the data from the network.viewWillAppear我检查用户是否已登录,如果是,则正在发出异步网络请求,一旦完成,该表将加载来自网络的数据。 However since the user is not logged in at this point, the table view is empty;但是由于此时用户还没有登录,表视图是空的;
- the user taps on the search box; - 用户点击搜索框; because he's not logged in, B is pushed (after a confirmation);因为他没有登录,B被推送(确认后);
- he logs in successfully in B, then presses a button which pops B and shows A again; - 他在 B 中成功登录,然后按下一个按钮,弹出 B 并再次显示 A;
- at this point in time, because he's logged in, from viewWillAppear I do the async request; - 在这个时间点,因为他已经登录,所以从viewWillAppear我做了异步请求;
- when that is completed, I call reloadData on the table view. - 完成后,我在表视图上调用reloadData

What I notice is that numberOfRowsInSection: is called and it returns the correct result, however cellForRowAtIndexPath: is NOT called afterwards and the table remains empty.我注意到的是numberOfRowsInSection:被调用并返回正确的结果,但是cellForRowAtIndexPath:之后没有被调用并且表保持为空。

I've checked and reloadData is called on the main thread.我已经检查并在主线程上调用了reloadData

Any idea what can it be?知道它是什么吗? Cause it's driving me nuts!因为它让我发疯!

Thanks,谢谢,
S. S。

EDIT: Here's the async bit of code from viewWillAppear in A.编辑:这是 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];
        }
    }];
}

I've checked that the async request completes successfully and that response contains the correct data (this is the array used to back the UITableView ).我已经检查了异步请求是否成功完成并且该response包含正确的数据(这是用于支持UITableView的数组)。

After reloadData , I've put a breakpoint in tableView:numberOfRowsInSection: and it stops there and it returns the correct number of elements in array .reloadData之后,我在tableView:numberOfRowsInSection:放置了一个断点,它停在那里并返回array正确数量的元素。 After that, however, the breakpoint in tableView:cellForRowAtIndexPath: is never hit.然而,在那之后, tableView:cellForRowAtIndexPath:的断点永远不会被命中。

One valid scenario for why numberOfRowsInSection would be called but cellForRowAtIndexPath would not be called is when the size or positioning of the table does not require any rows to be displayed.为什么会调用numberOfRowsInSection但不会调用cellForRowAtIndexPath一种有效情况是当表的大小或位置不需要显示任何行时。

For example, let's say you had a table that was 20 pixels high, but the header for the first section was 30 high and you returned nil for the header (or did not implement viewForHeaderInSection ).例如,假设您有一个 20 像素高的表格,但是第一部分的标题是 30 高,并且您为标题返回了 nil(或者没有实现viewForHeaderInSection )。 In this case, no rows would be displayed and it would look like the table just isn't there.在这种情况下,不会显示任何行,并且看起来表格不存在。

I see you are using IB.我看到你在使用 IB。 The sizing of the table can be deceptive in IB as it is assuming header and footer sizes.表格的大小在 IB 中可能具有欺骗性,因为它假设页眉和页脚大小。 I would log the frame for the table so you understand where it is when the appliction is run (versus where it appears in IB).我会记录表格的框架,以便您了解应用程序运行时的位置(相对于它出现在 IB 中的位置)。 I would also be sure to manually size and position the table's frame before calling reloadData.我还要确保调用 reloadData之前手动调整表格框架的大小和位置。 This will solve this valid case where cellForRowAtIndexPath is not called.这将解决未调用cellForRowAtIndexPath这种有效情况。

Check that the numberOfSectionsInTableView is not returning 0.检查numberOfSectionsInTableView是否没有返回 0。

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

I had the exact same issue and the problem was that I was trying to call reloadData: from another thread.我遇到了完全相同的问题,问题是我试图从另一个线程调用 reloadData: 。 The solution would be:解决方案是:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.tableView reloadData];
});

If you are using a different dataSource, as I was, make sure you are retaining the dataSource.如果您像我一样使用不同的数据源,请确保保留数据源。 Merely instantiating the class that will be the dataSource and assigning it via tableView.dataSource = myDataClass will not be sufficient as the dataSource property of a tableView is weak and will be released when viewDidLoad completes.仅仅实例化将成为数据源的类并通过tableView.dataSource = myDataClass分配它是不够的,因为 tableView 的 dataSource 属性很弱,并且会在 viewDidLoad 完成时释放。 All of the other methods were being called for me — even, surprisingly, heightForRowAtIndexPath — so this took me some time to debug.所有其他方法都被我调用了——甚至,令人惊讶的是, 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;

If a Table View inside a view that conflicts something like Scrool View, it does not called.如果视图中的表视图与 Scrool 视图之类的内容发生冲突,则不会调用它。 You should separate the views in your Storyboard or *.xib file.您应该将 Storyboard 或 *.xib 文件中的视图分开。

// True
    ▼ View
        ► Table View
        ► Scrool View
        ► Constraints

// False
    ▼ View
        ► Scrool View
            ► Table View
        ► Constraints

We had the same/similar issue.我们有相同/相似的问题。 The code reached numberOfSections and numberOfRowsInSection (and it even returned values) but could not reach cellForRowAt .代码达到了numberOfSectionsnumberOfRowsInSection (它甚至返回了值)但无法达到cellForRowAt At the time, Table View in the Storyboard had only constraints for right side, left side and top, but not for bottom.当时,Storyboard 中的 Table View 只有右侧、左侧和顶部的约束,而没有底部的约束。 Once we added constraint to the bottom, it worked like a charm.一旦我们在底部添加约束,它就像一个魅力。

So, check that you provide all needed constraints for the Table View.因此,请检查您是否为表视图提供了所有需要的约束。

Everyone keeps talking about height, but my TableView in a StackView with leading alignment ended up with 0 width.每个人都在谈论高度,但我在StackView TableView以领先对齐结束,宽度为 0。

Make sure to check if your TableView is correct size using Debug View Hierarchy .确保使用Debug View Hierarchy检查您的TableView的大小是否正确。

If you are using auto layout like me and adding tableview to your view controller's view make sure you have added this line when you are allocating your table view.如果您像我一样使用自动布局并将 tableview 添加到视图控制器的视图中,请确保在分配 table view 时添加了这一行。

tableView?.translatesAutoresizingMaskIntoConstraints = false

Silly mistake from my side.我这边的愚蠢错误。

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

I am using a customer datasource and it was released.我正在使用客户数据源,它已发布。 Because it is a weak reference of tableview.因为它是tableview的弱引用。

This is embarrassing and perplexing, but here's my fix.这令人尴尬和困惑,但这是我的解决方案。

My code:我的代码:

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

So the weird part is: the identifier _scanResultTable was never declared in my code, anywhere in the project.所以奇怪的部分是:标识符 _scanResultTable 从未在我的代码中声明,在项目的任何地方。 I have no idea how this compiled (and I recompiled several times).我不知道这是如何编译的(我重新编译了几次)。

My root cause was that I had linked my table output to scanResultTable in my ViewController, but was referring to it as _scanResultTable.我的根本原因是我已将表输出链接到 ViewController 中的scanResultTable ,但将其称为 _scanResultTable。 Once I started using scanResultTable like I should've been, things cleared up.一旦我开始像我应该使用的那样使用scanResultTable ,事情就清楚了。 This makes me wonder if objective-c has something special about leading underscores in identifiers...这让我想知道objective-c是否有一些关于标识符中前导下划线的特殊之处......

Edit: It does !编辑: 确实如此 Good lord I can't wait to never touch this language again.天哪,我迫不及待地不想再碰这种语言了。

Wasted hours and then found out that my tableview was inside a stackview.浪费了几个小时,然后发现我的 tableview 在 stackview 中。 As soon as I removed the stackview, it worked like a charm.一旦我删除了堆栈视图,它就像一个魅力。 For me it's Xcode 11.3 .对我来说是 Xcode 11.3 。

I'm using ReactiveCocoa.我正在使用 ReactiveCocoa。 So I've created the model for table view.所以我为表视图创建了模型。 The data was prepared to be displayed, so numberOfRows and so on was called.数据已准备好显示,因此numberOfRows等。 But I haven't added the tableview as subview, thus cellForRowAtIndexPath was not called)))但是我没有将 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]; 
}

In my case, I had the TableView inside a StackView .就我而言,我在StackViewTableView When I put it outside the StackView it worked.当我把它放在 StackView 之外时,它起作用了。

Try to insert new rows manually instead of [self.tableView reloadData] :尝试手动插入新行而不是[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];

In dataSource method return incremented int _rowsNumber :在 dataSource 方法中返回递增的int _rowsNumber

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

i solved same issue by checking tableViewCell identifier.我通过检查 tableViewCell 标识符解决了同样的问题。 Go To Attributes İnspector and look at identifier section.转到属性检查器并查看标识符部分。 Probably is missing.大概是失踪了。 So write cell identifier.所以写单元格标识符。

Same case here, but it was a mistake:同样的情况,但这是一个错误:

I included a Scrollview with 2 tablesViews inside a ViewController (design requirements), in the scrollview controller I created the ViewControllers (that contains the TableViews) programatically and I used a weak var to store it, bad idea because they were released at the end of viewDidLoad method.我在 ViewController 中包含了一个带有 2 个表视图的 Scrollview(设计要求),在滚动视图控制器中我以编程方式创建了 ViewControllers(包含 TableViews),我使用了一个变量来存储它,坏主意,因为它们是在年底发布的viewDidLoad 方法。

If you don't see your tableview content, please, check if it was released.如果您没有看到您的 tableview 内容,请检查它是否已发布。

My mistake was very brain-painful for me because all methods (delegate&datasource) were called except viewForCell...我的错误对我来说非常痛苦,因为除了 viewForCell 之外,所有方法(委托和数据源)都被调用了......

I have same issue i have use Table View inside the StackView and table view scroll disable and set height constrain but after that我有同样的问题,我在 StackView 和 table view 中使用了 Table View 滚动禁用并设置高度约束,但在那之后

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

Not working stop calling this method all Data Source and Delegate set properly.不工作停止调用此方法所有Data SourceDelegate设置正确。

if you have same issue than Solution is set Table View bottom , leading , trailing constrain如果您遇到与解决方案相同的问题,则设置表视图底部、前导、尾随约束

在此处输入图片说明

None of the answers here helped me.这里的答案都没有帮助我。

I was using doing my constraints programmatically but forgot to write:我正在以编程方式使用我的约束,但忘了写:

myTableView.translatesAutoresizingMaskIntoConstraints = false

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

这可能太明显了,但在我的情况下,我正在以编程方式删除一个元素(标签),该元素是对表格顶部边距的引用,因此委托/源不是问题,而是表格的内容存在问题-大小/高度,这个冲突产生了一个奇怪的行为,调用 numberOfRowsInSection 而不是 cellForRowAt indexPath

Are you sure that after the user logged in and B is popped the viewWillAppear method in A gets called in order to perform the refresh?您确定在用户登录并弹出 B 后,会调用 A 中的viewWillAppear方法以执行刷新吗?

If you show B as a modal controller, when you dismiss it you won't have the viewWillAppear method called.如果您将 B 显示为模态控制器,当您关闭它时,您将不会调用viewWillAppear方法。

As far as I know, viewWillAppear/viewDidAppear (and other like it) are events generated by the UINavigationController in the case of navigation events (push/pop viewcontrollers).据我所知, viewWillAppear/viewDidAppear (以及其他类似的)是 UINavigationController 在导航事件(push/pop viewcontrollers)的情况下生成的事件。 So maybe that is why you eventually get your refresh when you leave A and return ... it all depends on the way to display the next viewcontroller.所以也许这就是为什么当你离开 A 并返回时你最终会刷新......这一切都取决于显示下一个视图控制器的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM