tableView: cellForRowAtIndexPath: вызываться не только для видимых ячеек? - PullRequest
8 голосов
/ 15 февраля 2012

У меня есть tableView с разделами, которые можно открывать и закрывать. Поэтому, когда я нажимаю на раздел, чтобы открыть его, он заполняется ячейками, и -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) вызывается ровно столько раз, сколько я указал в -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section.

Это правильно? Разве это не просто количество видимых клеток?

Потому что в моем случае у меня плохая ситуация: у меня много пользовательских ячеек (50 ~ 100 ячеек), и вызов -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) для каждой ячейки замедляет открытие раздела, потому что каждый раз, когда выполняется чтение из пера и содержимое ячейки заполняется изображением. Я проверил видимость ячейки внутри -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) вот так:

if ([[self.tableView indexPathsForVisibleRows] containsObject:indexPath])
    NSLog(@"visible %@", indexPath);

и это показывает, что из 45 ячеек видны только 6 или 7. Другие находятся вне видимой области. Но создание ячеек все еще выполняется. Вот код:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath    {
static NSString *CellIdentifier = @"IVCell";
IVCamera *camera = [server.cameras objectAtIndex:indexPath.row];

IVServerListViewCell *cell = (IVServerListViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    [[NSBundle mainBundle] loadNibNamed:@"IVServerListCell" owner:self options:nil];
    cell = (IVServerListViewCell*)_tableViewCell;
    self.tableViewCell = nil;

}

[cell textLabel].text = camera.cameraName;
cell.preview = camera.preview;
cell.userData = camera; 
cell.isEnabled = (server.isInactive)?NO:camera.isOnline;

return cell;
}

Это все еще правильно? Или я что-то упустил?

Ответы [ 7 ]

5 голосов
/ 15 февраля 2012

Ну, я как-то справился со своей проблемой. Вот мои идеи и мысли, как я пришел к решению. Может быть, это кому-нибудь пригодится.

Я дал инструкции по распределению памяти и стеку вызовов с помощью инструментов во время открытия раздела. Это показало мне, что большая часть времени уходит на загрузку ячейки из nib-файла.

Во-первых, я только что уменьшил размер файла пера , то есть минимизировал количество представлений, используемых в пользовательской ячейке табличного представления (теперь это только 2 представления и 2 метки вместо 6 представлений, 2 изображения и 2 этикетки до). Это дало мне некоторое улучшение в загрузке клеток. Документация Apple предлагает использовать как можно меньше просмотров и не использовать прозрачность. Так что будьте внимательны к этим предложениям.

Во-вторых, как я обнаружил ранее, что видны не все ячейки, созданные -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *), я решил каким-то образом уменьшить количество загрузок новых ячеек из файла nib. Чтобы достичь этого, я пришел к простой идее: вернуть пустые ячейки по умолчанию для невидимых строк, а загрузить пользовательские ячейки из перьев для видимых. Вот кусок кода:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([self index:indexPath isInvisibleInTableView:tableView])
        return [self getBlankCellForTableView:tableView];

    // the rest of the method is the same
    ...
}

-(BOOL)index:(NSIndexPath*)indexPath isInvisibleInTableView:(UITableView*)tableView
{
    NSMutableArray *visibleIndexPaths = [self getExtendedVisibleIndexPathsForTableView:tableView];

    return ![visibleIndexPaths containsObject:indexPath];
}

-(UITableViewCell*)getBlankCellForTableView:(UITableView*)tableView
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"IVBlankCell"];
    if (!cell)
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"IVBlankCell"] autorelease];

    return cell;
}

Как видите, я не использую просто метод -(NSArray*)indexPathsForVisibleRows просмотра таблиц для обнаружения видимых ячеек. Вместо этого я написал свой собственный метод -(NSMutableArray*)getExtendedVisibleIndexPathsForTableView:(UITableView*)tableView. Это было необходимо, потому что по какой-то причине при использовании -(NSArray*)indexPathsForVisibleRows ячейки, которые находятся рядом с последней видимой ячейкой, или ячейки, предшествующие первой видимой ячейке, создавались как пустые ячейки и выглядели как пустые ячейки при прокрутке. Чтобы преодолеть это, в -(NSMutableArray*)getExtendedVisibleIndexPathsForTableView: (UITableView*)tableView я добавляю граничные ячейки в видимые ячейки массива:

-(NSMutableArray*)getExtendedVisibleIndexPathsForTableView:(UITableView*)tableView{
    NSArray *visibleIPs = [tableView indexPathsForVisibleRows];

    if (!visibleIPs || ![visibleIPs count])
        return [NSMutableArray array];

    NSIndexPath *firstVisibleIP = [visibleIPs objectAtIndex:0];
    NSIndexPath *lastVisibleIP = [visibleIPs objectAtIndex:[visibleIPs count]-1];

    NSIndexPath *prevIndex = ([firstVisibleIP row])?[NSIndexPath indexPathForRow:[firstVisibleIP row]-1  inSection:[firstVisibleIP section]]:nil;
    NSIndexPath *nextIndex = [NSIndexPath indexPathForRow:[lastVisibleIP row]+1 inSection:[lastVisibleIP section]];

    NSMutableArray *exVisibleIndexPaths = [NSMutableArray arrayWithArray:[tableView indexPathsForVisibleRows]];

    if (prevIndex)
        [exVisibleIndexPaths addObject:prevIndex];
    [exVisibleIndexPaths addObject:nextIndex];

    return exVisibleIndexPaths;
}

Таким образом, я сократил время открытия разделов с большим количеством пользовательских ячеек, что было доказано при трассировке инструментов и их использовании во время работы с приложением.

2 голосов
/ 08 января 2015

проверьте размер таблицы.может быть, ваша высота просмотра таблицы очень велика, и она продолжает загружать ячейки, пока ваша ячейка не заполнит все размеры таблицы.

1 голос
/ 20 июня 2018

Просто добавьте приблизительную высоту для UITableViewCell

Проблема В моем случае было: cellforRowAtIndexPath вызывался array.count количество раз, в то время как отображаемые ячейки были меньше, чем array.count.

Чтобы решить эту проблему, я только что заменил

  • (CGFloat) tableView: (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath

with,

  • (CGFloat) tableView: (UITableView) tableView оцененныйHeightForRowAtIndexPath: (ненулевой NSIndexPath) indexPath;
1 голос
/ 05 июня 2018

увеличьте

РасчетныйВысота UITableview.

0 голосов
/ 22 января 2014

Добавление else решило мою проблему.Где я сбросил все изменения, которые были внесены в ячейку.

if (! self.cell) {
    self.cell = [[LanguageCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    self.cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
    self.cell.checkImage.image = NO;

}
0 голосов
/ 07 января 2013

Я использовал похожую технику, но так как indexPathsForVisibleRows отсортирован, вам не нужно использовать containsObject.Вместо этого вы можете просто сделать:

//
// Checks if indexPath is visible in current scroll state, we are expanding bounds by 1
// because the cells that are next to the last one visible or the cells that are previous
// to the first one visible could look empty while scrolling.
//
- (BOOL)isIndexPathVisible:(NSIndexPath *)indexPath
{
    NSInteger row = [indexPath row];
    NSArray *visible = [self.tableView indexPathsForVisibleRows];
    NSInteger count = [visible count];
    NSInteger first = (count > 0) ? MAX([visible[0] row] - 1, 0): 0;
    NSInteger last = (count > 1) ? [visible[1] row] + 1: first + 2;

    return row >= first && row <= last;
}

Кстати;это предполагает, что вы используете только один раздел.Это не будет работать для более чем одного раздела.

0 голосов
/ 15 февраля 2012

Это кажется правильным, да.Идея оптимизации самой загрузки заключается в том, как работает "dequeueReusableCellWithIdentifier".если вы загружаете изображение из удаленного местоположения, это то место, где вы хотели бы оптимизировать код.но не от загрузки ячеек, поскольку здесь это выглядит правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...