Добавление UIView в UITableViewCell через cell.contentView - PullRequest
4 голосов
/ 02 января 2011

У меня есть класс GraphView, расширяющий UIView, который в основном рисует маленькую небольшую линейную диаграмму. Мне нужен один из этих графиков в верхней части каждого раздела в моем UITableView. Поэтому я попытался создать отдельную ячейку в верхней части одного из моих разделов, а затем в этой ячейке я сделал:

[cell.contentView addSubview:graphView];
[graphView release];

Но когда я прокручиваю вниз, график выглядит сбойным и появляется в случайных местах вдоль UITableView. У кого-нибудь есть идеи или понимание? Есть ли лучший способ добавить другой UIView в верхнюю часть каждого раздела в моем UITableView?

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //NSLog(@"cellForrowAtIndexPath");
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
    }
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.textLabel.font = [UIFont systemFontOfSize:12];
    cell.detailTextLabel.font = [UIFont systemFontOfSize:12];


    NSString *str1, *str2;
    if(indexPath.section == 0) {
        if(indexPath.row == 0) {

            str1 = @"";
            str2 = @"";

            S7GraphView *graphView = [[S7GraphView alloc] initWithFrame:CGRectMake(10,0,310,100)];
            graphView.dataSource = self;

            NSNumberFormatter *numberFormatter = [NSNumberFormatter new];
            [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
            [numberFormatter setMinimumFractionDigits:0];
            [numberFormatter setMaximumFractionDigits:0];

            graphView.yValuesFormatter = numberFormatter;

            NSDateFormatter *dateFormatter = [NSDateFormatter new];
            [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
            [dateFormatter setDateStyle:NSDateFormatterShortStyle];

            graphView.xValuesFormatter = dateFormatter;

            [dateFormatter release];        
            [numberFormatter release];

            graphView.backgroundColor = [UIColor whiteColor];

            graphView.drawAxisX = NO;
            graphView.drawAxisY = YES;
            graphView.drawGridX = NO;
            graphView.drawGridY = YES;

            graphView.xValuesColor = [UIColor blackColor];
            graphView.yValuesColor = [UIColor blackColor];

            graphView.gridXColor = [UIColor blackColor];
            graphView.gridYColor = [UIColor blackColor];

            graphView.drawInfo = NO;
            graphView.info = @"Load";
            graphView.infoColor = [UIColor whiteColor];


            //When you need to update the data, make this call:

            //[graphView reloadData];

            //S7GraphView *graphView = [[S7GraphView alloc] initWithFrame:CGRectMake(10,0,320,300)];
            //self.graphView.dataSource = self;
            [cell.contentView addSubview:graphView];
            [graphView release];
        }

Ответы [ 4 ]

13 голосов
/ 02 января 2011

Табличное представление работает немного иначе, чем вы могли бы ожидать вначале.По сути, только ячейки, которые вы видите, загружаются в память.Если подумать, это имеет смысл - если у вас в таблице 10 000 элементов, все загружены в память, ваше приложение исчерпает память и довольно быстро падает.

Когда вы прокручиваете, ваши ячейкисоздано в реальном времени.Запутанная часть: ваши ячейки не создаются с нуля, вместо этого iOS просто берет ячейку, которая только что покинула экран, и снова отправляет ее через

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

.Таким образом, подпредставление, которое вы добавили в верхнюю ячейку, не будет удалено, когда эта ячейка будет повторно использована дальше при прокрутке.Краткий ответ: убедитесь, что вы удалили / сбросили подпредставление в функции выше, таким образом вы «сбросите» все использованные ячейки, которые используются далее в представлении таблицы.

Почему iOS делает это таким образом?Эффективность - в принципе, создать ячейку таблицы очень дорого.Поиск ширины, цвета, рисование фигуры ... + много чего еще занимает много сил процессора и времени.Гораздо эффективнее повторно использовать ячейки каждый раз, а не начинать с нуля.

Поэтому сбросьте только необходимые поля ячейки в функции создания ячейки.Таким образом, у вас будет плавная и быстрая прокрутка, но представления / свойства вашей ячейки будут сброшены до повторного использования ячейки.

Сначала сбиваетесь с толку?Ага.Но определенно лучший способ сделать это.

10 голосов
/ 08 февраля 2012

Я решил использовать теги:

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
    }
    else{
      [[cell.contentView viewWithTag:500] removeFromSuperview];
    }

    ...

    graphView.tag = 500;
    [cell.contentView addSubview:graphView];

   }
4 голосов
/ 04 января 2011

Хорошо, вот так:

static NSString *CellIdentifier = @"Cell";   

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) 
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
    }

//now remove any subview a reused cell might have:   
[cell.contentView.view removeFromSuperview];   
//and in part of the method, you'll need to create the subview if the cell is in the top row.

if (indexPath.row == 0)
{
    [cell.contentView.view addSubview:graphView.view];
}

В вашем случае это может немного отличаться из-за графического представления, а не UIView.Но это определенно основа того, как это должно выглядеть.

Надеюсь, это поможет!

3 голосов
/ 02 января 2011

Это, как я думал, проблема повторного использования ячейки:

каждый раз, когда выполняется tableView:cellForRowAtIndexPath:, вы добавляете еще один экземпляр GraphView. В сочетании с повторным использованием ячеек, когда объекты ячеек переназначаются на другие indexPaths, это приводит к большим проблемам.

Вы должны добавлять подпредставления только внутри if (cell == nil).

Вам придется отдельно отслеживать ваши GraphViews. Либо добавив их в NSDictionary с indexPaths в качестве ключа, либо создав подкласс UITableViewCell.

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