Ios 为什么有时会在节中的行数之前调用索引路径中的行高度?
我有这个密码Ios 为什么有时会在节中的行数之前调用索引路径中的行高度?,ios,tableview,realm,Ios,Tableview,Realm,我有这个密码 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { UnlockTableSectionHeaderType type = (UnlockTableSectionHeaderType) [self.sections[section] integerValue]; switch (type) { case UnlockTab
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
UnlockTableSectionHeaderType type = (UnlockTableSectionHeaderType) [self.sections[section] integerValue];
switch (type) {
case UnlockTableSectionTypeAllLeaderBoard:
return 1;
case UnlockTableSectionTypeTopic:
NSLog(@"%@", [self.topicController showLoading] ? @"YES" : @"NO");
NSLog(@"%d", [self.topicController loadedItemCount]);
return [self.topicController showLoading] ? 1 : [self.topicController loadedItemCount];
case UnlockTableSectionTypeCategory:
return [self.categoryController showLoading] ? 1 : [self.categoryController loadedItemCount];
default:
return 0;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return [UnlockTableSectionHeaderView defautHeight];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UnlockTableSectionHeaderType type = (UnlockTableSectionHeaderType) [self.sections[indexPath.section] integerValue];
NSInteger row = indexPath.row;
switch (type) {
case UnlockTableSectionTypeAllLeaderBoard:
return 207.0f;
case UnlockTableSectionTypeTopic:
NSLog(@"heightForRow %@", [self.topicController showLoading] ? @"YES" : @"NO");
NSLog(@"heightForRow %d", [self.topicController loadedItemCount]);
return [self.topicController showLoading] ? 130.0f :
[TopicCell heightForTopicCellForThread:[self.topicController itemForIndex:row] showCategory:YES];
case UnlockTableSectionTypeCategory:
return 120.0f;
}
return 0.0f;
}
它尝试使用控制器显示数据(controller
类似于负责从web和领域查询数据的控制器)
这是我的日志
Sent message: 41|{"id":51,"m":"group.getAllUnlock","p":[{"limit":15,"skip":0}]} <-- call to server
Sent message: 41|{"id":52,"m":"thread.queryUnlock","p":[{"limit":15,"skip":0}]} <-- call to server
YES
0
heightForRow YES
heightForRow 0
YES
0
heightForRow YES
heightForRow 0
YES
0
heightForRow YES
heightForRow 0
YES
0
heightForRow YES
heightForRow 0
heightForRow YES
heightForRow 0
heightForRow YES
heightForRow 0
YES
0
heightForRow YES
heightForRow 0
YES
0
heightForRow YES
heightForRow 0
Got response for RPC call 52, 34 bytes <-- response from server
Zip size: 838
Got response for RPC call 51, 3087 bytes <-- response from server
heightForRow NO <-- Height For Row called first
heightForRow 0
WARNING: GoogleAnalytics 3.10 void GAIUncaughtExceptionHandler(NSException *) (GAIUncaughtExceptionHandler.m:49): Uncaught exception: Index 0 is out of bounds (must be less than 0)
但不知何故,numberOfRowsInSection
没有被调用
它在这一排崩溃了
return [self.topicController showLoading] ? 130.0f :
[TopicCell heightForTopicCellForThread:[self.topicController itemForIndex:row] showCategory:YES];
我怎样才能解决这个问题?
谢谢
更新
现在看看stacktrace,很抱歉之前没有包括它,我现在不能做,因为我们已经更改了设计。通过删除主题并只保留类别,现在我们只有一种类型的控制器,崩溃消失了。。。似乎每个部分都有两种类型的数据源存在问题,当其中一种更新而另一种仍在更新时,会导致崩溃
无论如何,要了解更多信息,请从cellforrowatinexpath
中的此行调用heightforrowatinexpath
if (type == UnlockTableSectionTypeTopic) {
if ([self.topicController showLoading]) {
return [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([LoadingTableViewCell class]) forIndexPath:indexPath];
}
// Below line is the line which called `heightForRowAtIndexPath` when looking into the stacktrace
TopicCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([TopicCell class]) forIndexPath:indexPath];
cell.delegate = self;
[cell configureCellForThread:[self.topicController itemForIndex:row]
lastCell:row == [self.topicController loadedItemCount] - 1
showCategory:YES];
return cell;
}
但我不知道为什么此时调用了
cellforrowatinexpath
,这是由苹果定义的。但是当你仔细想想的时候,这是有道理的。如果行数占全屏高度,则询问另一个部分的行数是没有意义的。可以随时调用heightForRowAtIndexPath:
和cellForRowAtIndexPath:
方法,例如在滚动期间。当表视图知道基础数据已更改时,它将只调用numberofrowsinssection:
。这就是reloadData
调用的目的:告诉表视图数据已经更改,它需要重新初始化表
因此,更新主线程上的底层数据(在您的示例中是Realm)非常重要,然后立即调用reloadData
您的
[self.topicController showLoading]
似乎是一种避免这样做的变通方法。这可以很好地工作,但是您需要确保更改showLoading
状态,并在主线程上调用reloadData
那么,委托方法的调用顺序是由Apple定义的吗?您的topicController
做什么?尤其是在itemForIndex:
中?这是直接委托给领域集合吗?另外,如何将更新从领域通知传播到视图控制器?这是同步发生的吗?当您调用“reloadData”时,日志不会显示。可能坠机发生在那之前?听起来很像是线程问题,你在后台线程上更新了底层数据。@marius唯一要做的事情是itemForIndex:
return self.items[index]代码>其中self.items
是RLMResults
。在viewDidLoad:
中,通过从领域(如果有,它将不显示加载单元格)进行查询来初始化,并向服务器进行查询。当结果返回时,它会将数据保存到领域,并且self上的领域通知将被委派回去并调用reloadData
。可以理解的是,屏幕外的部分不会调用numberOfRowsInSection:。但是,也绝对不应该为这些部分调用HeightForRowatineXpath:
。调用HeightForRowatineXpath:来计算右侧滚动条的大小和位置。为此,它当然需要在HeightForRowatineXpath:之前调用numberOfRowsInSection:。也就是说,不这样做是没有意义的。没错,我还没有完全想清楚这一点。
if (type == UnlockTableSectionTypeTopic) {
if ([self.topicController showLoading]) {
return [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([LoadingTableViewCell class]) forIndexPath:indexPath];
}
// Below line is the line which called `heightForRowAtIndexPath` when looking into the stacktrace
TopicCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([TopicCell class]) forIndexPath:indexPath];
cell.delegate = self;
[cell configureCellForThread:[self.topicController itemForIndex:row]
lastCell:row == [self.topicController loadedItemCount] - 1
showCategory:YES];
return cell;
}