你好:我在我的应用程序中使用了一个集合视图,我注意到使用reloadData
刷新需要比预期更长的时间。我的收藏视图有1 section
,我正在用5 cell
s(每个有2个按钮和一个标签)测试它。我在代码中放入了一些日志,以显示系统实际上需要刷新多长时间。有趣的是,日志表明它比现在刷新得更快。在设备上,例如,它会占用到约0.2秒(明显),但这里有日志:UICollectionView reloadData看起来很慢/迟缓(不是瞬时的)
0.007s
从时间reloadData
被调用时cellForItemAtIndexPath
被称为第一次
0.002s
每个单元加载并返回
0.041s
从时间reloadData
调用到小区#5返回
有没有什么在cellForItemAtIndexPath
功能(巴斯特别强烈的时候cally只能在NSArray
的indexPath
的row
处找到一个有3个值的字典。 即使当我删除这个,只是返回一个空白按钮的单元格,但我看到了相同的行为。
有没有人有任何想法,为什么这可能会发生?顺便说一下,它只发生在物理设备(iPad Air)上。谢谢!
编辑#1
每@布莱恩 - 镍的评论,我所使用的时间轮廓仪,并发现它不是每次reloadData
被称为确实秒杀。下面是截图:
@ArtSabintsev,这里是周边reloadData
通话功能,其次是cellForItemAtIndexPath
:
//Arrays were just reset, load new data into them
//Loop through each team
for (NSString *team in moveUnitsView.teamsDisplaying) { //CURRENT TEAM WILL COME FIRST
//Create an array for this team
NSMutableArray *teamArr = [NSMutableArray new];
//Loop through all units
for (int i = [Universal units]; i > 0; i--) {
//Set the unit type to a string
NSString *unitType = [Universal unitWithTag:i];
//Get counts depending on the team
if ([team isEqualToString:currentTeam.text]) {
//Get the number of units of this type so that it supports units on transports. If the territory is a sea territory and the current unit is a ground unit, check the units in the transports instead of normal units
int unitCount = (ter.isSeaTerritory && (i == 1 || i == 2 || i == 8)) ? [self sumOfUnitsInTransportsOfType:unitType onTerritory:ter onTeam:team] : [ter sumOfUnitsOfType:unitType onTeam:team];
//Get the number of movable units on this territory
int movableCount = 0;
if (queue.selectedTerr != nil && queue.selectedTerr != ter) { //This is here to prevent the user from selecting units on another territory while moving units from one territory
movableCount = 0;
} else if (ter.isSeaTerritory && (i == 1 || i == 2 || i == 8)) { //Units on transports - can be an enemy territory
movableCount = [self sumOfUnitsInTransportsOfType:unitType onTerritory:ter onTeam:team];
} else if ([Universal allianceExistsBetweenTeam:team andTeam:ter.currentOwner] || i == 3 || i == 9) { //Other units - only planes can be on an enemy territory
movableCount = [ter sumOfMovableUnitsOfType:unitType onTeam:team];
}
//See if there are units of this type on this territory on this team
if (unitCount > 0) {
//Add data to this team's dictionary
NSMutableDictionary *unitInfo = [NSMutableDictionary new];
[unitInfo setObject:@(i) forKey:@"UnitTag"];
[unitInfo setObject:unitType forKey:@"UnitType"];
[unitInfo setObject:@(unitCount) forKey:@"Count"];
[unitInfo setObject:@(movableCount) forKey:@"MovableCount"];
[unitInfo setObject:team forKey:@"Team"];
//Add the dictionary
[teamArr addObject:unitInfo];
//Increment the counter
if (unitsOnCT) { //Must check or it could cause a crash
*unitsOnCT += 1;
}
}
}
}
//Add the team array
[moveUnitsView.unitData addObject:teamArr];
}
//Reload the data in the collection view
[moveUnitsView.collectionV reloadData];
而且我cellForItemAtIndexPath
的相关代码:
//Dequeue a cell
UnitSelectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"UnitSelectionCell" forIndexPath:indexPath];
//Get the team array (at the index of the section), then the unit's data (at the index of the row)
NSMutableDictionary *unitData = (moveUnitsView.unitData[indexPath.section])[indexPath.row];
//Get values
int unitTag = [[unitData objectForKey:@"UnitTag"] intValue];
int count = [[unitData objectForKey:@"Count"] intValue];
int movableCount = [[unitData objectForKey:@"MovableCount"] intValue];
NSString *unitType = [unitData objectForKey:@"UnitType"];
//Set the cell's values
[cell.upB addTarget:self action:@selector(upMoveUnits:) forControlEvents:UIControlEventTouchUpInside]; [cell.upB setTag:unitTag];
[cell.iconB setBackgroundImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[Universal imageNameForUnit:unitType team:[unitData objectForKey:@"Team"]] ofType:nil]] forState:UIControlStateNormal];
[cell.iconB setTitle:[Universal strForExpDisplay:count] forState:UIControlStateNormal];
[Universal adjustTitlePlacementOfB:cell.iconB autosize:FALSE]; //Don't autosize because this is a collection view
cell.unitTypeL.text = unitType;
cell.unitTypeL.adjustsFontSizeToFitWidth = cell.unitTypeL.adjustsLetterSpacingToFitWidth = TRUE;
//Set fonts
[Universal setFontForSubviewsOfView:cell];
//Return the cell
return cell;
初始化收集视图时,使用以下方式注册单元:
[moveUnitsView.collectionV registerNib:[UINib nibWithNibName:@"UnitSelectionCell" bundle:nil] forCellWithReuseIdentifier:@"UnitSelectionCell"];
编辑#2
@roycable和@亚伦 - brager指出,这可以通过使用imageWithContentsOfFile:
引起的。为了验证这一点,我改变cellForItemAtIndexPath
这样:
//Dequeue a cell
UnitSelectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"UnitSelectionCell" forIndexPath:indexPath];
//Get the team array (at the index of the section), then the unit's data (at the index of the row)
NSMutableDictionary *unitData = (moveUnitsView.unitData[indexPath.section])[indexPath.row];
//Get values
int unitTag = [[unitData objectForKey:@"UnitTag"] intValue];
[cell setBackgroundColor:[UIColor redColor]];
[cell.upB removeTarget:nil action:NULL forControlEvents:UIControlEventTouchUpInside];
[cell.upB addTarget:self action:@selector(upMoveUnits:) forControlEvents:UIControlEventTouchUpInside]; [cell.upB setTag:unitTag];
//Return the cell
return cell;
奇怪的是,这似乎并没有解决问题。这个功能在字面上并没有做任何强化任务,但它似乎仍然滞后(而时间分析器似乎也证实了这一点)。
在回答Universal
代码的请求,而不是张贴代码,我就总结一下吧:
+units
刚刚返回17
+unitWithTag:
使用switch
得到相应之间的数量NSString
+allianceExistsBetweenTeam:
看看数组是否包含其中一个字符串
+setFontForSubviewsOfView:
是,基本上使用this code
不幸的是递归函数,这似乎不是很重要,因为这个问题仍与过于简单cellForItemAtIndexPath
机能发生。
我还实施了@ aaron-brager的新建议。在添加新的之前,我删除了target
,并对Time Profiler进行了更改。我没有看到任何东西真的弹出...这是截图。有关UIImage
一切都无关紧要这个问题,因为是NSKeyedArchiver
,所以唯一的其他东西,真正意义的字符串,数组和字典:
任何及所有的帮助感激 - 我真的需要得到这个固定的(因此赏金)。谢谢!
编辑#3 - 确定解决方案
所以,事实证明,这个问题是不是在任的那些功能。问题在于上面称为更新功能的功能(我们称之为Function A
)(我们称之为Function B
)。在Function A
之后调用Function B
,它执行了一项CPU密集型任务。我没有意识到reloadData
是at least partially asynchronous这个事实,所以我假设CPU密集型任务和reloadData
最终都在争夺CPU时间。我解决我的问题,加入以下权利之前return cell;
:
if (indexPath.row == [self collectionView:collectionView numberOfItemsInSection:indexPath.section] - 1) {
[self performSelector:@selector(performMyCPUIntensiveTask:) withObject:myObject afterDelay:0.1];
}
我希望这可以帮助别人,将来别人。感谢所有帮助过我的人,我衷心感谢。
您是否使用过[时间分析器](https://developer.apple.com/Library/ios/documentation/AnalysisTools/Reference/Instruments_User_Reference/TimeProfilerInstrument/TimeProfilerInstrument.html)?如果您遇到200毫秒的延迟,您应该在重新加载后看到一个很好的高峰。 – 2014-09-04 00:41:42
你介意给我们提供你所有的示例代码吗?另外,你使用可重复使用的单元格吗? – ArtSabintsev 2014-09-04 00:46:25
感谢您的回复,伙计们。我已经添加了有关您的评论的信息 - 请参阅我的编辑。 – rebello95 2014-09-04 00:57:17