2010-10-10 3 views
0

Désolé pour le titre long. En substance, je veux accomplir la même chose que l'application de calendrier pour les détails de l'événement. La première cellule indique le titre et la date de l'événement. La seconde affiche une alerte, s'il y en a une, sinon Notes, s'il y en a, ou rien d'autre si aucun de ces champs n'est présent.Modifier le nombre de différentes UITableViewCells avec un ordre particulier comme l'application Calendrier

La façon dont je fais est maintenant un très long si la condition dans cellForRowAtIndexPath:

if(indexPath.row == 0) { 
    TitleCell *titlecell = [[TitleCell alloc] init]; 
    // config cell to do title here, always 
    return titlecell; 
} else if (indexPath.row == 1 && foo) { 
    FooCell *foocell = [[FooCell alloc] init]; 
    // config cell to show foo, if it exists 
    return foocell; 
} else if (indexPath.row == 1 && bar) { 
    BarCell *barcell = [[BarCell alloc] init]; 
    // foo doesn't exist, but bar, so show bar in cell 1 
    return barcell; 
} // etc etc 

qui est vraiment laid, et que je crée les cellules dans le cas et le retour, l'analyseur statique me dire que chaque l'un d'entre eux est une fuite potentielle. Il n'y en a pas d'autre, car j'ai besoin de couvrir tous les scénarios de toute façon, et cela donne aussi un avertissement sur la méthode potentiellement ne rien retourner.

Y a-t-il un meilleur moyen de rendre ce produit plus propre et de ne pas me donner d'avertissement?

Merci!

Christoph

Répondre

2

Les avertissements sont parce que sont fuite de mémoire, vous devez libérer la cellule: TitleCell *titlecell = [[[TitleCell alloc] init] autorelease];. Il y a aussi une chance de ne pas avoir une déclaration de retour parce que vous n'avez pas else dans votre bloc if.

Voici une autre façon de le faire:


// Call this beforehand 
- (void)loadTable { 
    // Since we are not using objects, we need to use a non-retaining array 
    // A better way of doing this would be with delegates or NSInvocations 
    array = (NSMutableArray*)CFArrayCreateMutable(NULL, 0, NULL); 
    [array addObject:(id)@selector(buildTitleCell)]; 
    if (foo) 
    [array addObject:(id)@selector(buildFooCell)]; 
    if (bar) 
    [array addObject:(id)@selector(buildBarCell)]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (indexPath.row < array.count) { 
    SEL selector = (SEL)[array objectAtIndex:indexPath.row]; 
    return [self performSelector:selector]; 
    } 
    return nil; 
} 

- (UITableViewCell*)buildTitleCell { 
    TitleCell *titlecell = [[[TitleCell alloc] init] autorelease]; 
    // config cell to do title here, always 
    return titlecell; 
} 
... 

EDIT: fixe comme par @ commentaire de Christoph

+0

Merci, mais je ne suis pas sûr que ça marchera si Foo n'existe pas. Dans ce cas, Bar devrait être dans la cellule 1. Ou est-ce que je manque quelque chose? – Christoph

+0

Vous avez raison, je l'ai réparé maintenant. – Aleph7

+0

Merci à vous deux d'avoir fait remarquer que je suis, en fait, une fuite de mémoire. J'ai choisi cela comme la réponse acceptée pour son code. – Christoph

1

Clang a raison quand il dit que vous êtes une fuite mémoire - Le UITableView conserve les UITableViewCell s que vous lui donnez, vous devriez donc être les autoreleasing dans cellForRowAtIndexPath. Au lieu d'utiliser if déclarations, je pense que vous devriez utiliser un switch.

+0

Oh wow, tu as raison. Doit avoir manqué la autorelease dans le modèle de Xcode et juste ne l'ai pas remis quand j'ai changé des trucs autour. Merci! – Christoph

Questions connexes