2013-08-19 4 views
0

Я новичок. Я использую этот код для создания UITableViewCell, но когда я перезагружаю таблицу, изображение кнопки не всегда корректно, хотя все ярлыки работают нормально. Я не знаю почему. Как я могу исправить эту проблему?Как правильно повторно использовать ячейку в UITableView

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

    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; 

     UILabel *FileNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 100, 30)]; 
     FileNameLabel.tag = 1000; 
     FileNameLabel.backgroundColor = [UIColor clearColor]; 
     FileNameLabel.font = [UIFont fontWithName:@"Helvetica" size:16]; 
     FileNameLabel.font = [UIFont boldSystemFontOfSize:16]; 
     FileNameLabel.textColor = [UIColor blackColor]; 
     [cell.contentView addSubview: FileNameLabel]; 
     [FileNameLabel release]; 


     UILabel *UploadTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 20, 150, 25)]; 
     UploadTimeLabel.tag = 2000; 
     UploadTimeLabel.backgroundColor = [UIColor clearColor]; 
     UploadTimeLabel.font = [UIFont fontWithName:@"Helvetica" size:12]; 
     UploadTimeLabel.textColor = [UIColor grayColor]; 
     [cell.contentView addSubview: UploadTimeLabel]; 
     [UploadTimeLabel release]; 


     UILabel *pricelabel = [[UILabel alloc] initWithFrame:CGRectMake(80, 0, 80, 30)]; 
     pricelabel.backgroundColor = [UIColor clearColor]; 
     pricelabel.font = [UIFont fontWithName:@"Helvetica" size:16]; 
     pricelabel.font = [UIFont boldSystemFontOfSize:16]; 
     pricelabel.textColor = [UIColor darkGrayColor]; 
     pricelabel.tag = 3000; 
     //pricelabel.hidden = YES; 
     pricelabel.textAlignment = NSTextAlignmentRight; 
     [cell.contentView addSubview: pricelabel]; 
     [pricelabel release]; 


     market = [[UIButton alloc] init];; 
     [market setFrame:CGRectMake(200, 6, 30, 30)]; 
     market.tag = 4000; 

     [market addTarget:self action:@selector(marketPressedAction:) forControlEvents:UIControlEventTouchDown]; 


     [cell.contentView addSubview:market]; 
    } 

    if([temp count] > 0) 
    { 
     UILabel *fileNameLbl = (UILabel*)[cell.contentView viewWithTag:1000]; 
     fileNameLbl.text =[temp objectAtIndex:indexPath.row]; 

     UILabel *uploadlbl = (UILabel*)[cell.contentView viewWithTag:2000]; 
     uploadlbl.text =[UploadTimeAllArr objectAtIndex:indexPath.row]; 
    } 

    UIButton *marketButton = (UIButton*)[cell.contentView viewWithTag:4000]; 
    [marketButton setTag:indexPath.row]; 
    if([sellingArray count]>0) 
    { 
     NSLog(@"sellingArray %@",sellingArray); 
     if([[sellingArray objectAtIndex:indexPath.row] isEqualToString:@"0"]) // nothing 
     { 

      [marketButton setSelected:NO]; 
      [marketButton setImage:[UIImage imageNamed:@"Marketplace.png"] forState:UIControlStateNormal]; 
      marketButton.enabled = YES; 

     } 
     else if([[sellingArray objectAtIndex:indexPath.row] isEqualToString:@"2"]) // marketplace 
     { 

      [marketButton setSelected:YES]; 
      [marketButton setImage:[UIImage imageNamed:@"MarketplaceSelect.png"] forState:UIControlStateNormal]; 
      marketButton.enabled = YES; 

     } 
    } 


    return cell; 
} 
+0

У вас есть дополнительная строка в коде UIButton. Вы загружаете два экземпляра. Первый экземпляр с 'alloc - init'. Второй с кнопкой 'buttonWithType: UIButtonTypeCustom'. Я не знаю, что происходит под дугой в этой ситуации, но я считаю, что его называли оборванным указателем. – Justin

ответ

1

Основная проблема заключается в том, что каждый раз, когда вызывается этот метод, вы воссоздаете новые представления в своей камере. Вы хотите создать все элементы многократного использования внутри if(cell == nil), иначе он сделает дубликаты. Все, что является динамическим, должно создаваться вне этого. Я взял ваш код и изменил его. Это должно работать лучше.

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     // Everything that does not change should go in here! 

     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; 
     UILabel *pricelabel = [[UILabel alloc] initWithFrame:CGRectMake(80, 0, 80, 30)]; 


     pricelabel.backgroundColor = [UIColor clearColor]; 
     pricelabel.font = [UIFont fontWithName:@"Helvetica" size:16]; 
     pricelabel.font = [UIFont boldSystemFontOfSize:16]; 
     pricelabel.textColor = [UIColor darkGrayColor]; 
     pricelabel.tag = 3000; 
     //pricelabel.hidden = YES; 
     pricelabel.textAlignment = NSTextAlignmentRight; 
     [cell addSubview:pricelabel]; 

     UIButton *market = [UIButton buttonWithType:UIButtonTypeCustom]; 
     [market setFrame:CGRectMake(200, 6, 30, 30)]; 
     [market addTarget:self action:@selector(marketPressedAction:) forControlEvents:UIControlEventTouchDown]; 
     [cell addSubview:market]; 
    } 

    // find market button, since we could be reusing a cell we cannot rely on a tag 
    // value to find it. (This would only work with one button though). 
    UIButton *market; 
    for (UIView *subview in cell.subviews) { 
    if ([subview isKindOfClass:[UIButton class]]) { 
      market = (UIButton *)subview; 
      break; 
     } 
    } 

    // set all defaults in case of reuse 
    [market setImage:[UIImage imageNamed:@"DefaultImage.png"] forState:UIControlStateNormal]; 
    market.selected = YES; 
    market.enabled = NO; 
    market.clearsContextBeforeDrawing = NO; 

    if([sellingArray count] > 0) { 
     NSLog(@"sellingArray %@",sellingArray); 
     if([[sellingArray objectAtIndex:indexPath.row] isEqualToString:@"0"]) { 
      // not sure if this is supposed to be YES or NO 
      market.clearsContextBeforeDrawing = YES; 
      [market setSelected:NO]; 
      [market setImage:[UIImage imageNamed:@"Marketplace.png"] forState:UIControlStateNormal]; 
      market.enabled = YES; 
     } 
    } 
    [market setTag:indexPath.row]; 

    return cell; 
} 

Поскольку вы не используете ARC, убедитесь, что вы просматриваете этот код для любого необходимого подсчета ссылок.

+0

Я пробовал свой код, но он тоже такой же, он все еще не может изменить изображение при перезагрузке. У вас есть другие решения? спасибо –

+0

Я отлаживаю когда reloadData, marketButton 0x0000. он не может инициализировать? –

+0

Я изменил код, посмотрю. Также, где вы называете reloadData? Я думаю, нам может понадобиться больше вашего кода. – Firo

0

Второе редактирование:

Это был скопирован из ответа выше:

внутри -cellForRowAtIndexPath: метода:

if (!cell) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellSubtitle]; 
     UIButton *market = [UIButton buttonWithType:UIButtonTypeCustom]; 
      [market setFrame:CGRectMake(200, 6, 30, 30)]; 
     [market addTarget:self action:@selector(marketPressedAction:)  forControlEvents:UIControlEventTouchDown]; 

     [cell.contentView addSubview:market]; 

    //Add all your UILabel INITIATION stuff here as well 

    } 

    UIButton *marketButton; 
    for (UIView *subview in cell.subviews) {  
     if ([subview isKindOfClass:[UIButton class]]) { 
      marketButton = (UIButton *)subview; 
      break;   
     }  
    } 
    marketButton.tag = [indexPath row]; 

    UILabel *priceLabel = [cell.contentView viewWithTag:3000]; 
    UILabel *uploadTimeLabel = [cell.contentView viewWithTag:2000]; 

    //Set up your labels and button now 

    return cell; 
} 


    EDIT: Leaving my original answer below for posterity but I see that you are setting the table index row as the MarketButton's tag. If you're using that to figure out which dataSource object to query, this is bad practice. You should be making a custom cell which can hold a reference to the object in your data source, so you don't have to ask the button for its tag, and then ask the data source array for the object at index:tag. 

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

Единственное, что я могу изменить в ответе Фиро, это просто добавить свойство «тег» к каждому виду в ячейке, так что вам не придется перебирать каждый раз, когда вы хотите его найти.

Также вынул линию [[UIButton alloc]init], потому что это излишний и может считаться оборванным указателем.

if (cell == nil) { 
    // Everything that does not change should go in here! 

    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; 
    UIButton *market = [UIButton buttonWithType:UIButtonTypeCustom]; 
    [market setFrame:CGRectMake(200, 6, 30, 30)]; 
    [market addTarget:self action:@selector(marketPressedAction:) forControlEvents:UIControlEventTouchDown]; 

    market.tag = 9999; 

    [cell.contentView addSubview:market]; 
} 

//don't have to do UIView iteration here 
UIButton *marketButton = [cell.contentView viewWithTag:9999]; 
+0

Спасибо, но я попробовал ваш код, но когда reloadData, он все еще не может отобразить правильное изображение в UIButton marketButton. –

+0

Я отлаживаю когда reloadData, marketButton 0x0000. он не может инициализировать? –

+0

Вы удалили вызов в 'market.tag = [indexPath row]' позже в методе?Если вы оставите его там, больше не будет '-viewWithTag: 9999' – Justin

0

dequeReusablecellWithIdentifier: метод получить возвращают экземпляр ячейки уже создан доступным, если опорные точкам еще до нуля, нам нужна действительная ячейка и создать одну ячейку, чтобы вернуться из этого cellForRowatIndexpath: method.That является то, что проверяется в (cell ==nil). Когда вы создаете новую ячейку, вы создаете , создавая, и, следовательно, все настройки настраиваются и все должно быть сделано здесь.

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