2013-06-18 2 views
0

ситуации:UITableViewController загружает все мои клетки при прокрутке

У меня есть контроллер представления, которое имеет вид таблицы, которая принимает данные из массива. Поскольку данные этого массива довольно медленны для загрузки, я загружаю элементы по требованию (запускается в tableView: cellForRowAtIndexPath :).

Проблема:

В начале (то есть после того, как вид сделал нагрузки) он загружает только видимые ячейки (первые 6). Но тогда, когда вы пытаетесь прокрутить, он загружает всех остальных сразу! (Тестировано в контрольной точке нагрузки, по-видимому [UITableView _createPreparedCellForGlobalRow: withIndexPath:] вызывается для каждой строки)

Кодекс:

PlayerListDataModel.m

@implementation PlayerListDataModel 
(...) 
-(NSString *)nombre { 
    if (!self.loaded) [self load]; 
    return _nombre; 
} 
-(void)load { 
    NSLog(@"Loading %d", self.sqlId); 
    [OMNIGAME loadListCell:self]; 
    self.loaded = YES; 
} 
@end 

PlayerListViewController.m

@implementation PlayerListViewController 

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } 

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    return self.jugadores.count; 
} 

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
static NSString* cellId = @"PlayerListCell"; 
    PlayerListCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId]; 
    if (!cell) { 
     cell = [[PlayerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId]; 
    } 
    PlayerListDataModel* data =[self.jugadores objectAtIndex:indexPath.row]; 
    cell.dem = data.bestDem; 
    cell.nombre = data.nombre; 
    cell.apellido = data.apellido; 
    cell.escudo = data.escudo; 
    cell.equipo = data.equipo; 
    cell.age = data.edad; 
    cell.bandera = data.bandera; 
    cell.price = data.price; 
    cell.energia = data.energy; 
    cell.valor = data.valor; 

    return cell; 
} 
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
    return tableView.bounds.size.height/7; 
} 
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    return tableView.bounds.size.height/7; 
} 
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 
    if (!self.search) { 
     self.search = [[PlayerSearchView alloc] init]; 
     self.search.search.delegate = self; 
    } 
    return self.search; 
} 

Вопрос:

Это намеренное поведение? Если это так, если есть способ взломать его? Если нет, что я делаю неправильно?

+0

Вы имеете в виду, что загружают все, все сразу? Или вы имеете в виду, что он создает новую ячейку для каждой строки и никогда не использует ее повторно? Примечание. Вы создаете новый PlayerDataModel, используется ли ячейка повторно или нет. – AMayes

+0

Да, все они сразу, alomst 12.000 ... (О вашей заметке: [Player DataModel load] вызывается только один раз на экземпляр, потому что он устанавливает свой загруженный флаг в true) – BerinHardt

+0

Вы, в любой момент, расширяете высоту вашего столаView? – AMayes

ответ

1

Это неожиданное и действительно непреднамеренное поведение. Я не знаю реализации вашей пользовательской ячейки, но я не мог себе представить, что это может привести к такому поведению. На мой взгляд, с вашей реализацией -tableView ничего не получается: cellForRowAtIndexPath: сам.

Мое подозрение заключается в том, что либо (i) при запуске в какой-то мере прокручивает границы вашего вида таблицы, либо (ii) некоторые инструменты, установленные на вашем Mac, мешают вашему симулятору. Поэтому мои предложения заключаются в следующем:

(i) Поскольку Dhruv Goel предлагает попробовать hardcoding высоту строк. Если границы вашего таблицы должны сокращаться, это может привести к некоторым осложнениям (чем ниже высота строки, тем больше строк должно быть поставлено в очередь). Но я не могу представить себе, почему это должно произойти.

(ii) Вы отлаживаете свое приложение исключительно с помощью тренажера? Если это так, ознакомьтесь с этой ссылкой: UITableViewCell cellForRowAtIndexPath calling large number of rows when first scrolling. Возможно, что такие инструменты, как управление окнами, мешают симулятору.

Последний вопрос приводит меня к другому вопросу. Вы проверили, возникает ли эта проблема в других подклассах UITableViewController (в этом конкретном проекте)?

+1

You проблема была в Cinch. Это сводило меня с ума. – BerinHardt

+0

Yup, Cinch была для меня проблемой. –

0

Да, это предполагаемое поведение. Фактически, это одна из основных функций UITableView. Он просто сохраняет в памяти ячейки, которые должны отображаться в настоящее время. Таким образом, когда вы прокручиваете, представление таблицы деактивирует старые ячейки один за другим и повторно использует их новыми данными. Так что в вашем случае сначала 5 или 6 клетки в поле зрения, и вы перечисляете и необходимы новые клетки, линия:

PlayerListCell* cell = [tableView dequeueReusableCellWithIdentifier:cellId]; 

пытается повторно использовать клетки, если это возможно, а если нет, то новые клетки создаются с:

if (!cell) { 
cell = [[PlayerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId]; 
} 

хак вокруг этого было бы не из очереди клеток, а также создавать (Alloc INIT) новый сотовый каждый раз, но это не рекомендуется.

+0

Я не мог объяснить себя. Я говорю, что я ** НЕ ** хочу загрузить их все сразу, но это происходит – BerinHardt

+0

А я вижу .. вы можете поместить NSLog (@ "номер ячейки:% d", indexPath.row). где-то внутри вашего метода cellForRowAtIndexPath, запустите его, немного прокрутите и скажите, что это последний оператор журнала в консоли? номер ячейки: X –

+0

Путь к ячейке: 0, 11865 – BerinHardt

0

Это не ошибка, это задокументировано.

Метод делегата:

tableView:heightForHeaderInSection: 

вызывается для каждой ячейки в вашем Tableview независимо от того, какие из них находятся на экране.

Поскольку обсуждение в документации говорит:

Обсуждение

Метод позволяет делегат указать строки с различной высоты. Если этот метод реализован, возвращаемое значение переопределяет значение, указанное для свойства rowHeight для UITableView для данной строки.

Последствия для использования tableView: heightForRowAtIndexPath: вместо свойства rowHeight. Каждый раз, когда отображается табличное представление, он вызывает tableView: heightForRowAtIndexPath: на делегате для каждой из его строк, что может привести к значительной проблеме с производительностью, когда представление таблицы имеет большое количество строк (приблизительно 1000 или более)

Смежные вопросы