Привет: Я использую представление коллекции в своем приложении, и я заметил, что для обновления требуется больше времени, чем ожидалось, используя reloadData
. Моя коллекция имеет 1 section
, и я тестирую ее с помощью 5 cell
s (каждая из которых имеет 2 кнопки и ярлык). Я поместил несколько журналов в свой код, чтобы показать, сколько времени система действительно принимает для обновления. Интересно, что журналы показывают, что он освежает быстрее, чем он. На устройстве, например, он будет принимать до ~ 0.2sec (заметно), но вот журналы:UICollectionView reloadData кажется медленным/отстающим (не мгновенным)
0.007s
Со времени reloadData
называется ко времени cellForItemAtIndexPath
называется в первый раз
0.002s
за ячейку для загрузки и быть возвращены
0.041s
Со времени reloadData
называется ко времени, когда клетка # 5 возвращается
Существует нет ничего особенно интенсивно в cellForItemAtIndexPath
функции (Basi cally просто находит словарь с 3 значениями в пределах NSArray
по адресу indexPath
row
). Даже когда я удалил это и просто вернул ячейку с пустой кнопкой, я увидел такое же поведение.
Есть ли у кого-нибудь идеи, почему это может произойти? Это происходит только на физическом устройстве (iPad Air). Благодаря!
EDIT # 1
Per @ комментарий Брайен-никелевые, я использовал инструмент Time Profiler, и обнаружили, что это действительно шип каждый раз 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"];
EDIT # 2
@roycable и @ Aarón-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;
Как ни странно, это не похоже, чтобы исправить эту проблему. Это буквально не делает интенсивных задач в этой функции, но все еще кажется отстающим (и Time Profiler, похоже, подтверждает это).
В ответ на просьбы о предоставлении кода из Universal
, вместо размещения кода я просто резюмировать:
+units
просто возвращает 17
+unitWithTag:
использует switch
, чтобы возвращать NSString
соответствующее число между
+allianceExistsBetweenTeam:
видит, если массив содержит один из строк
+setFontForSubviewsOfView:
рекурсивная функция, которая в основном использует this code
К сожалению, это не представляется весьма актуальной, поскольку данный вопрос все еще происходит с упрощенным cellForItemAtIndexPath
функции.
Я также внедрил новые предложения @ aaron-brager. Я удалил target
перед добавлением нового, и я внес изменения в Time Profiler. Я не видел ничего действительно выскочить ... Вот скриншот. Все, что связано с UIImage
не имеет никакого отношения к этому вопросу, как NSKeyedArchiver
, так что только другие вещи, которые действительно имеют смысл являются строки, массивы и словари:
Любое помощь очень ценится - Я на самом деле нужно получить это исправление (отсюда и щедрость). Спасибо!
Edit # 3 - Решение идентифицированного
Таким образом, получается, что этот вопрос не был ни в одном из этих функций. Проблема была в функции (назовем ее Function A
), которая назвала функцию обновления выше (назовем ее Function B
). Сразу после Function A
, получившего название Function B
, он выполнял задачу с интенсивным использованием ЦП. Я не знал о том, что reloadData
- at least partially asynchronous, поэтому я беру на себя задачу с интенсивным процессором, а reloadData
закончил гонку за процессорное время. Я решил свою проблему, добавив следующее прямо перед return cell;
:
if (indexPath.row == [self collectionView:collectionView numberOfItemsInSection:indexPath.section] - 1) {
[self performSelector:@selector(performMyCPUIntensiveTask:) withObject:myObject afterDelay:0.1];
}
Я надеюсь, что это помогает кто-то еще в будущем. Спасибо всем, кто помог, я искренне ценю это.
Используете ли вы [Time Profiler] (https://developer.apple.com/Library/ios/documentation/AnalysisTools/Reference/Instruments_User_Reference/TimeProfilerInstrument/TimeProfilerInstrument.html)? Если вы испытываете задержку в 200 мс, после перезагрузки вы должны увидеть хороший большой всплеск. –
Не могли бы вы предоставить нам весь ваш образец кода? Кроме того, вы используете многоразовые ячейки? – ArtSabintsev
Спасибо за ваши ответы, ребята. Я добавил информацию в ответ на оба ваших комментария - см. Мое редактирование. – rebello95