UITableView reloadData - cellForRowAtIndexPath 未触发

Posted

技术标签:

【中文标题】UITableView reloadData - cellForRowAtIndexPath 未触发【英文标题】:UITableView reloadData - cellForRowAtIndexPath not fired 【发布时间】:2010-08-12 18:41:30 【问题描述】:

我有 splitViewController,它有一些 viewController 作为 MasterViewController 和一些 tableViewController 作为 DetailViewController。当我按下 masterViewController 上的按钮时,我想在 detailViewController 中显示新的 tableViewController 而不是现有的。

所以我这样做了:

SearchDetailViewController *searchDetailViewController = [[SearchDetailViewController alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *searchDetailNavigationController = [[UINavigationController alloc] initWithRootViewController:searchDetailViewController];

之后我传递数据以显示在新的 tableController 中:

[searchDetailViewController passInSearchResults:listOfItems];

之后我将新控制器“推送”到 splitViewController:

[searchSplitViewController setViewControllers:[NSArray arrayWithObjects:self.navigationController, searchDetailNavigationController, nil]];

在目标tableViewController 方法“passInSearchResults”中传递了数据,我也调用了reloadData。方法如下:

- (void)passInSearchResults:(NSMutableDictionary *)searchResults 
    self.searchResultList = searchResults;
    NSLog(@"Data is passed in: %@",self.searchResultList);
    [self.tableView reloadData];
    //[self.tableView setNeedsDisplay];

控制台:数据传入:[这里我得到了我想要的确切数据,而且看起来恰到好处]。

After this I see that method "numberOfRowsInSection" is fired:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    NSLog(@"Setting table length: %i",[self.searchResultList count]);
    return [self.searchResultList count];

控制台:设置表格长度:[这里我得到正确的长度]

问题是表格没有被传递的数据填充并且方法“cellForRowAtIndexPath”没有被调用。

怎么可能在 reloadData 方法“numberOfRowsInSection”被触发,但没有方法“cellForRowAtIndexPath”...... ???

谢谢

【问题讨论】:

【参考方案1】:

调用[self.tableView reloadData];时检查你是否在主线程中

- (void)passInSearchResults:(NSMutableDictionary *)searchResults 
 if ([NSThread isMainThread]) 
    self.searchResultList = searchResults;
    NSLog(@"Data is passed in: %@",self.searchResultList);
    [self.tableView reloadData];

else 
    [self performSelectorOnMainThread:@selector(passInSearchResults:) searchResults waitUntilDone:NO];

【讨论】:

不必先检查是否在主线程上运行。 performSelectorOnMainThread 有效,即使您已经在主线程上,dispatch_async( dispatch_get_main_queue() 也是如此(这可能是您真正想要的)。在此处添加 if 只会消耗不必要的处理器周期。【参考方案2】:

怎么可能在 reloadData 方法“numberOfRowsInSection”被触发,但没有方法“cellForRowAtIndexPath”...... ???

在同样的问题上花了一天的时间后,我想我们在这里发现了一个错误。不过,我确实找到了破解/解决方法。

如果我更改在我的 cellForRowAtIndexPath 方法中使用的数组(添加/删除值或完全重新构建它),它似乎在您重新加载数据时再次正确调用 cellForRowAtIndexPath。

例如,在我的 cellForRowAtIndexPath 中,我有类似的内容:

cell.textLabel.text = [[[self.searchResultsArrayWithSections objectAtIndex:indexPath.section] objectForKey:@"rowValues"] objectAtIndex:indexPath.row];

    return cell;

我还有一个方法来构建这个在 viewDidLoad 上调用的数组:

    - (NSMutableArray *)splitIntoSectionsWithAlphabet:(NSMutableArray *)myArray 
    
NSString *letters = @"abcdefghijklmnopqrstuvwxyz";
NSMutableArray *content = [NSMutableArray new];

//code to build array here, nothing special really

return content;

所以我注意到,如果我在调用 reloadData 之前专门在我的 searchResultsArrayWithSections 数组上再次调用此方法,它实际上会正确调用所有 UITableViewDelegate 方法! (就像我说的,破解但它有效!)

//dirty hack, bug with cancel button and not realoding data, seems we have to modify this array before it will work correctly
self.customerListArrayWithSections = [self splitIntoSectionsWithAlphabet:self.customerListArray];
[self.customerListTv reloadData];

【讨论】:

【参考方案3】:

检查你的numberOfRows,如果是0,没有单元格可以显示。

【讨论】:

【参考方案4】:

在我的例子中,问题是 reloadData() 函数不是从 主线程 调用的。

我已经通过将它放在 dispatch_async() 函数中进行了更改,从而解决了问题:

dispatch_async(dispatch_get_main_queue(), 
    self.tableView.reloadData()
)

希望这对其他人有所帮助。

【讨论】:

【参考方案5】:

我有同样的问题,但决定很简单。 首先,您可以尝试向下滚动表格吗? tableView:cellForRow... 应该被调用。 检查 tableView 的标题高度和 contentOffset。

【讨论】:

【参考方案6】:

您还可以在 viewController 的 init[With...] 方法中分配表,并在 IB 中连接相同的属性。这样,可能会调用 numberOf... 委托方法而 cellForRow... 不会。

【讨论】:

【参考方案7】:

我的“AutoLayouted” UITableView 没有在 reloadData 上调用 cellForRowAtIndexPath,因为我错误地设置了框架。

_tableView = [[UITableView alloc] initWithFrame:self.view.frame];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;

通过将其更改为 CGRectZero,它起作用了..

_tableView = [[UITableView alloc] initWithFrame:CGRectZero];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;

【讨论】:

以上是关于UITableView reloadData - cellForRowAtIndexPath 未触发的主要内容,如果未能解决你的问题,请参考以下文章

UITableView.reloadData() 没有刷新 tableView。没有错误信息

UITableView 的 reloadData() 的替代方案?

UIView 与 UITableview 和 UIImageview,使用 reloadData 访问 UITableview

UITableView 强制 sectionIndex 更新而不调用 reloadData

iOS UITableView reloadData 刷新结束后执行后续操作

调用 reloadData 时 UITableView 有不需要的动画