2010-04-02 7 views
1

J'apprends sur le SDK iPhone et ai une exception intéressante avec la gestion subview UITableViewCell quand un doigt est pressé sur certaines lignes.UITableViewCell sélectionnés fantômes subview

La table est utilisée pour attribuer des sons à des gestes de la main - le fait de balayer le téléphone dans l'une des 3 directions déclenche la lecture du son. La sélection d'une ligne affiche une feuille d'action avec 4 options pour l'affectation du son: gauche, bas, droite et annuler. Les sons peuvent être mappés dans une, deux ou trois directions de sorte que n'importe quelle cellule peut avoir l'un des sept états suivants: gauche, bas, droite, gauche et bas, gauche et droite, bas et droite ou gauche et droite. Si une ligne est mappée à l'un de ces sept états, une ou plusieurs flèches correspondantes sont affichées dans les limites de la ligne en tant que sous-vue. Les flèches vont et viennent comme elles le devraient dans un écran donné et lors du défilement.

Cependant, après un défilement vers un nouveau lot de lignes, ce n'est que lorsque j'appuie sur le doigt sur certaines lignes (mais pas toutes) qu'une flèche apparaît par magie dans l'arrière-plan d'état sélectionné. Lorsque je retire mon doigt de la rangée et que la feuille d'action apparaît, la flèche disparaît. Après avoir appuyé sur l'un des quatre boutons, je ne peux plus le reproduire. Mais c'est vraiment désorientant et déroutant de voir cette flèche flasher à l'écran parce que la ligne sélectionnée n'est assignée à rien.

Qu'est-ce que je n'ai pas pensé de faire ici? Tout mon code de table est collé ci-dessous et ceci est un screencast du problème: http://www.screencast.com/users/JonathanGCohen/folders/Jing/media/d483fe31-05b5-4c24-ab4d-70de4ff3a0bf

Est-ce que je gère mal mes sous-vues ou existe-t-il une propriété d'état sélectionnée qui me manque? Autre chose? Dois-je inclure d'autres informations dans ce post pour clarifier les choses? Je vous remercie!!

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

    NSUInteger section = [indexPath section]; 
    NSUInteger row = [indexPath row]; 
    NSString *key = [categories objectAtIndex:section]; 
    NSArray *nameSection = [categoriesSounds objectForKey:key]; 
    static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: 
          SectionsTableIdentifier]; 
    NSArray *sound = [categoriesSounds objectForKey:key]; 
    NSString *soundName = [[sound objectAtIndex: row] objectAtIndex: 0]; 
    NSString *soundOfType = [[sound objectAtIndex: row] objectAtIndex: 1]; 

    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] 
       initWithStyle:UITableViewCellStyleDefault 
       reuseIdentifier:SectionsTableIdentifier] autorelease]; 
    } 

    cell.textLabel.text = [[nameSection objectAtIndex:row] objectAtIndex: 0]; 

    NSUInteger soundSection = [[[sound objectAtIndex: row] objectAtIndex: 2] integerValue]; 
    NSUInteger soundRow = [[[sound objectAtIndex: row] objectAtIndex: 3] integerValue]; 

     NSUInteger leftRow = [leftOldIndexPath row]; 
     NSUInteger leftSection = [leftOldIndexPath section]; 
     if (soundRow == leftRow && soundSection == leftSection && leftOldIndexPath !=nil){ 
      [selectedSoundLeftAndDown removeFromSuperview]; 
      [selectedSoundLeftAndRight removeFromSuperview]; 
      [cell.contentView addSubview: selectedSoundLeft]; 
      selectedSoundLeft.frame = CGRectMake(200,8,30,30); 
     } 
     else { 
      [cell.contentView sendSubviewToBack: selectedSoundLeft]; 
     } 

     NSUInteger downRow = [downOldIndexPath row]; 
     NSUInteger downSection = [downOldIndexPath section]; 
     if (soundRow == downRow && soundSection == downSection && downOldIndexPath !=nil){ 
      [selectedSoundLeftAndDown removeFromSuperview]; 
      [selectedSoundDownAndRight removeFromSuperview]; 
      [cell.contentView addSubview: selectedSoundDown]; 
      selectedSoundDown.frame = CGRectMake(200,8,30,30); 
     } 
     else { 
      [cell.contentView sendSubviewToBack: selectedSoundDown]; 
     } 

     NSUInteger rightRow = [rightOldIndexPath row]; 
     NSUInteger rightSection = [rightOldIndexPath section]; 
     if (soundRow == rightRow && soundSection == rightSection && rightOldIndexPath !=nil){ 
      [selectedSoundDownAndRight removeFromSuperview]; 
      [selectedSoundLeftAndRight removeFromSuperview]; 
      [cell.contentView addSubview: selectedSoundRight]; 
      selectedSoundRight.frame = CGRectMake(200,8,30,30); 
     } 
     else { 
      [cell.contentView sendSubviewToBack: selectedSoundRight]; 
     } 

     // combos 
     if (soundRow == leftRow && soundRow == downRow && 
      soundSection == leftSection && soundSection == downSection){ 
      [selectedSoundLeft removeFromSuperview]; 
      [selectedSoundDown removeFromSuperview]; 
      [selectedSoundLeftAndDownAndRight removeFromSuperview]; 
      [cell.contentView addSubview: selectedSoundLeftAndDown]; 
      selectedSoundLeftAndDown.frame = CGRectMake(200,8,30,30); 
     } 
     else { 
      [cell.contentView sendSubviewToBack: selectedSoundLeftAndDown]; 
     } 
     if (soundRow == leftRow && soundRow == rightRow && 
      soundSection == leftSection && soundSection == rightSection){ 
      [selectedSoundLeft removeFromSuperview]; 
      [selectedSoundRight removeFromSuperview]; 
      [selectedSoundLeftAndDownAndRight removeFromSuperview]; 
      [cell.contentView addSubview: selectedSoundLeftAndRight]; 
      selectedSoundLeftAndRight.frame = CGRectMake(200,8,30,30); 
     } 
     else { 
      [cell.contentView sendSubviewToBack: selectedSoundLeftAndRight]; 
     } 
     if (soundRow == downRow && soundRow == rightRow && 
      soundSection == downSection && soundSection == rightSection){ 
      [selectedSoundDown removeFromSuperview]; 
      [selectedSoundRight removeFromSuperview]; 
      [selectedSoundLeftAndDownAndRight removeFromSuperview]; 
      [cell.contentView addSubview: selectedSoundDownAndRight]; 
      selectedSoundDownAndRight.frame = CGRectMake(200,8,30,30); 
     } 
     else { 
      [cell.contentView sendSubviewToBack: selectedSoundDownAndRight]; 
     } 
     if (soundRow == leftRow && soundRow == downRow && soundRow == rightRow && 
      soundSection == leftSection && soundSection == downSection && soundSection == rightSection){ 
      [selectedSoundLeftAndDown removeFromSuperview]; 
      [selectedSoundLeftAndRight removeFromSuperview]; 
      [selectedSoundDownAndRight removeFromSuperview]; 
      [selectedSoundLeft removeFromSuperview]; 
      [selectedSoundDown removeFromSuperview]; 
      [selectedSoundRight removeFromSuperview]; 
      [cell.contentView addSubview: selectedSoundLeftAndDownAndRight]; 
      selectedSoundLeftAndDownAndRight.frame = CGRectMake(200,8,30,30); 
     } 
     else { 
      [cell.contentView sendSubviewToBack: selectedSoundLeftAndDownAndRight]; 
     } 

    [indexPath retain]; 
    return cell;  
} 

Je voulais juste mettre une mise à jour sur cet article. J'ai passé 12 heures hier à essayer de résoudre ce problème et c'est juste au-delà de mes compétences actuelles. J'ai mis le style de sélection de cellule à zéro, ce qui est nul mais il est temps de jeter l'éponge pour l'instant.

Je suis complètement laissé tomber ce code en faveur de l'approche suivante, qui a vérifié tous les chemins d'index actuellement visibles pour la présence d'un chemin d'index attribué à un son, puis retiré subviews selon le cas:

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


/* NSArray *allVisibleCells = [table visibleCells]; 

    leftIsVisible = FALSE; 
    downIsVisible = FALSE; 
    rightIsVisible = FALSE; 

    NSLog(@"\n\n\n", (leftIsVisible ? @"TRUE" : @"FALSE")); 

    NSLog(@"Start: %@\n", (leftIsVisible ? @"TRUE" : @"FALSE")); 


    for (UITableViewCell *visibleCell in allVisibleCells){ 

     NSIndexPath *visibleCellIndexPath = [table indexPathForCell: visibleCell]; 
     NSLog(@"visible cell index path %@\n", visibleCellIndexPath); 

     if ([visibleCellIndexPath compare: leftOldIndexPath] == NSOrderedSame) { 
      leftIsVisible = TRUE; 
      NSLog(@"Compare successful: %@\n", (leftIsVisible ? @"TRUE" : @"FALSE")); 
     } 
     if ([visibleCellIndexPath compare: downOldIndexPath] == NSOrderedSame) { 
      downIsVisible = TRUE; 
     } 
     if ([visibleCellIndexPath compare: rightOldIndexPath] == NSOrderedSame){ 
      rightIsVisible = TRUE; 
     } 
    } 

    NSLog(@"After the first fast enumeration: %@\n", (leftIsVisible ? @"TRUE" : @"FALSE")); 
    NSLog(@"After check for left is still visible %@\n", (leftIsVisible ? @"TRUE" : @"FALSE")); 

    if(leftIsVisible == FALSE){ 
     [selectedSoundLeft removeFromSuperview]; 
     [selectedSoundLeftAndDown removeFromSuperview]; 
     [selectedSoundLeftAndRight removeFromSuperview]; 
     [selectedSoundLeftAndDownAndRight removeFromSuperview]; 
    } 
    if(downIsVisible == FALSE){ 
     [selectedSoundDownAndRight removeFromSuperview]; 
     [selectedSoundDown removeFromSuperview]; 
    } 
    if (rightIsVisible == FALSE){ 
     [selectedSoundRight removeFromSuperview]; 
    } */ 
+0

Kudos pour inclure le screencast mais 325 lignes de code est excessif et illisible dans ce format. Vous devriez pouvoir réduire le problème à moins de 50 lignes. Même si vous ne pouvez pas, vous devez utiliser PasteBin ou un service similaire pour publier de longues sections de code. Sinon, peu de gens prendront la peine de le lire. – TechZen

+0

Merci TechZen - J'ai réduit le code à l'origine du problème. Ce qui m'intéresse est que je ne vois que les sous-vues pendant l'état sélectionné. Mais je suis sûr qu'il y a quelque chose que je dois faire mieux quand je nettoie l'ardoise. –

Répondre

1

Je ne Vous n'avez pas le temps de parcourir 325 lignes de code, mais la cause la plus probable de votre problème est la réutilisation des cellules tableview sans avoir d'abord effacé leurs sous-vues.

Les flèches s'affichent dans des cellules non affectées car les objets réels sont réutilisés depuis les toutes premières lignes affichées. Puisque vous avez une sous-vue personnalisée, vous devez gérer cette sous-vue manuellement chaque fois que la cellule change d'information.

Chaque fois que vous réutilisez une cellule, votre première étape devrait être de l'effacer à son état de démarrage initial. Seulement alors devriez-vous charger de nouvelles données dans la cellule.

0

La bonne façon (comme le disent les Apple Docs) est d'utiliser des tags sur toutes les sous-vues. Si la cellule est créée (non supprimée/réutilisée), vous créez normalement la cellule, mais définissez une balise unique (entier, bien que vous puissiez utiliser define pour la rendre plus lisible). Si la cellule est retirée/réutilisée, vous obtenez la cellule en utilisant les balises. Regardez dans le Apple Docs en ligne pour personnaliser UItableViews et theres une section sur la personnalisation des cellules viewview.

Questions connexes