2013-04-03 7 views
7

Ich habe eine Mehrfachauswahlliste erstellt, die die Auswahl mehrerer Zutaten ermöglicht.UITableViewCell Wiederverwendung: Zelle wird falsch angezeigt - wird nicht wie erwartet wiederverwendet

In meiner Tabellenansicht können Zellen basierend auf der Listeneigenschaft eines Inhaltsstoffs entweder aktiviert oder deaktiviert werden. Wenn die Listeneigenschaft des Inhaltsstoffs festgelegt ist, wird die Zelle deaktiviert.

Wenn eine Zelle jedoch erneut verwendet wird, wird sie nicht wie erwartet angezeigt. Die Bilder unten erklären das Problem besser als ich.

(Die Zutaten, die nicht aktiviert werden sollten, sind: Kuchen-Zuckerglasur, Kondensmilch und Cournflour.)

  1. Das erste Bild zeigt die drei Bestandteile deaktiviert, und wie erwartet, annotiert.

  2. Im zweiten Bild zeigt das Scrollen nach unten jedoch, dass einige Zutaten deaktiviert sind (aber Sie können sie auswählen, und sie haben volle Interaktion).

  3. Das dritte Bild zeigt die Liste nach dem Zurückscrollen nach oben. Einige Zutaten wurden ausgegraut und Sie sehen, wie Maismehl als aktiviert angezeigt wird, obwohl Sie nicht interagieren/auswählen können.

Das Problem liegt in der Wiederverwendung von Zellen. Es scheint, dass die Zelle nicht "zurückgesetzt" wird, wenn sie erneut verwendet wird, und so etwas von ihrem "alten" Aussehen behält.

Unten ist der Code von cellForRowAtIndexPath:, da bin ich sicher, dass hier das Problem liegt (obwohl ich nicht sehen kann, was falsch ist).

- (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]; 
    }  

    // Fetches the corresponding Ingredient from the ingredientArray 
    Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row]; 

    if ([ingredient.list isEqualToString:@"Lardr"]) 
    { 
     cell.userInteractionEnabled = NO; 
     cell.detailTextLabel.text = @" Already in your Lardr"; 
    } 
    else if ([ingredient.list isEqualToString:@"Shopping List"]) 
    { 
     cell.userInteractionEnabled = NO; 
     cell.detailTextLabel.text = @" Already on your Shopping List"; 
    } 
    else 
    { 
     cell.userInteractionEnabled = YES; 
     cell.detailTextLabel.text = @""; 
    } 

    // Add a checkmark accessory to the cell if the ingredient is on the selectedIngredients array 
    if ([self.selectedIngredients containsObject:ingredient]) 
     cell.accessoryType = UITableViewCellAccessoryCheckmark; 
    else 
     cell.accessoryType = UITableViewCellAccessoryNone; 

    cell.textLabel.text = ingredient.name; 

    return cell; 
} 

Ich bin am Ende meiner Weisheit versucht, dies herauszufinden, und ich habe alle SO Fragen lesen, die auch nur entfernt verwandt sind, aber ohne Erfolg. Was ist das Problem?!


Meine Logik ist für jede Zelle, dass die textlabel, detailTextLabel, userInteractionEnabled und accessoryType Eigenschaften festgelegt sind, unabhängig davon, welche Ausführungspfad durch die if-Anweisungen, so kann ich nicht sehen, warum auch nach der Wiederverwendung, die Zelle wird nicht korrekt angezeigt.


EDIT: In einem Versuch, die Wurzel des Problems herauszufinden, habe ich versucht, „Zurücksetzen“, um die Zelle zurück, um es Standard ist, indem es die folgende rechts oberhalb der Linie, die die entsprechenden Zutaten holt: aber ohne Erfolg.

cell.userInteractionEnabled = YES; 
cell.textLabel.text = nil; 
cell.detailTextLabel.text = nil; 
cell.accessoryType = UITableViewAccessoryNone; 

Doch was ist interessant und völlig unlogisch - wenn ich die folgende Zeile cell.textLabel.text = ingredient.name bewegt, um direkt unterhalb der Zeile, die Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row]; liest, wird absolut kein Styling auf jede Zelle angewendet, obwohl Anwenderwechsel weiter unten gesetzt (und die relevanten Zellen sind wie erwartet deaktiviert).

Ich denke, ist die Reihenfolge, in der eine Zelleneigenschaften festgelegt sind, von Bedeutung? Ich weiß es sollte nicht, aber das Aussehen ändert sich basierend auf dem oben genannten.


Update: Ich habe das Problem gelöst; Siehe meine Antwort unten.

+0

Verwenden Sie StoryBoards? –

+0

Was macht den Text grau? –

+0

Mit dem von Ihnen geposteten Code ist nichts falsch. Wenn die Benutzerinteraktion auf NO gesetzt wird, wird der Text nicht grau dargestellt. Ich denke, dein Problem liegt wahrscheinlich bei der Methode, mit der du das machst. – rdelmar

Antwort

2

ich das Problem gelöst haben. Das Problem war, dass ich userInteractionEnabled gesetzt hatte, BEVOR man den Text der Zelle einstellte (danke an einen link von Carl Veazey in den Kommentaren).

Ich habe das Problem behoben, indem ich den Text der Zelle vor der Anpassung der Eigenschaft userInteractionEnabled gesetzt habe. Es wurde jedoch kein Styling auf die Zelle angewendet (obwohl die Zelle deaktiviert war). Ich musste daher manuell die Zelle formatieren, indem ich die textColor der Zelle einstelle. Unten ist der angepasste Code mit Kommentaren.

- (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]; 
    } 

    // Fetches the relevent ingredient from the ingredientArray 
    Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row]; 
    cell.textLabel.text = ingredient.name; // Moved this line before setting userInteractionEnabled 

    if ([ingredient.list isEqualToString:@"Lardr"]) 
    { 
     cell.userInteractionEnabled = NO; 
     cell.detailTextLabel.text = @" Already in your Lardr"; 
     cell.textLabel.textColor = [UIColor grayColor]; // Update the color accordingly 
    } 
    else if ([ingredient.list isEqualToString:@"Shopping List"]) 
    { 
     cell.userInteractionEnabled = NO; 
     cell.detailTextLabel.text = @" Already on your Shopping List"; 
     cell.textLabel.textColor = [UIColor grayColor]; 
    } 
    else 
    { 
     cell.userInteractionEnabled = YES; 
     cell.detailTextLabel.text = @""; 
     cell.textLabel.textColor = [UIColor blackColor]; 
    } 

    // Add a checkmark accessory to the cell if the ingredient is on the selectedIngredients array 
    if ([self.selectedIngredients containsObject:ingredient]) 
     cell.accessoryType = UITableViewCellAccessoryCheckmark; 
    else 
     cell.accessoryType = UITableViewCellAccessoryNone; 

    return cell; 
} 

Offensichtlich ist die Reihenfolge, in der die Eigenschaften einer Zelle gesetzt sollte irrelevant sein, und so bin ich sicher, dass dies ein Fehler ist. Ich hoffe, dies hilft jedem, der auf dasselbe Problem stößt.

0

Maintainthe Liste der ausgewählten Zelle in der Tabellenansicht, während die Zelle Wiederverwendung nur die Zelle überprüft bereits in Auswahlliste ist. Wenn JA, mach einfach deine Anpassung dort drüben. Versuchen Sie es so.

Declaration

TableViewCell *_selectedCell; 

die Linie Anpassen der ausgewählten Zelle und zu pflegen, die Auswahlliste zu speichern.

_selectedCell = (TableViewCell*)[self.ItemTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:rowIndex inSection:0]]; 

In cellForRowAtIndexPath Check aktuellen Zelle im

ist
if(_selectedCell) 
     [cell setBackgroundColor:[UIColor whiteColor]];// Customize the cell 
0

Verwendung des folgenden Codes mit einer Tabellenansicht Controller aus dem Storyboard, alles hat gut funktioniert. Es scheint, dass es einige Fehler mit der Tabellenansicht ist, die Sie standardmäßig erhalten, wenn nicht ein Storyboard mit:

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

    // Fetches the corresponding Ingredient from the ingredientArray 
    Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row]; 

    if ([ingredient.list isEqualToString:@"Lardr"]) 
    { 
     cell.userInteractionEnabled = NO; 
     cell.detailTextLabel.text = @" Already in your Lardr"; 
     cell.textLabel.textColor = [UIColor lightGrayColor]; 
    } 
    else if ([ingredient.list isEqualToString:@"Shopping List"]) 
    { 
     cell.userInteractionEnabled = NO; 
     cell.detailTextLabel.text = @" Already on your Shopping List"; 
     cell.textLabel.textColor = [UIColor lightGrayColor]; 
    } 
    else 
    { 
     cell.userInteractionEnabled = YES; 
     cell.detailTextLabel.text = @""; 
     cell.textLabel.textColor = [UIColor blackColor]; 
    } 

    if ([self.selectedIngredients containsObject:ingredient]) 
     cell.accessoryType = UITableViewCellAccessoryCheckmark; 
    else 
     cell.accessoryType = UITableViewCellAccessoryNone; 

    cell.textLabel.text = ingredient.name; 

    return cell; 
} 

Beachten Sie, dass ich dequeueReusableCellWithIdentifier verwenden: forIndexPath: statt dequeueReusableCellWithIdentifier :, und die if-Klausel zu beseitigen. Dies hat nichts mit Ihrem Problem zu tun, aber es ist die neueste Möglichkeit, dies für eine Tabellenansicht in einem Storyboard zu tun. explizit in willDisplayCell

+0

hast du den Fehler gezeigt? Mit anderen Worten, haben Sie gesehen, dass dieser Code anders funktioniert, wenn er auf Storyboard- und Nicht-Storyboard-Tabellen angewendet wird? es wäre sehr überraschend. – danh

+0

@danh, ja Ich habe den Fehler mit fast dem gleichen Code oben gezeigt - da er kein Storyboard hat, habe ich die übliche if (cell == nil) -Klausel hinzugefügt. Aber abgesehen davon war der Code identisch mit dem, was ich oben gepostet habe. Ich habe nur einen Tabellenansicht-Controller im App-Delegaten initialisiert, und ich sah das gleiche Verhalten wie das, was das OP gepostet hat. – rdelmar

2

Set Farbe Ihrer Zelle

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{ 

Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row]; 

    if ([ingredient.list isEqualToString:@"Lardr"]) 
    { 
     cell.textLabel.textColor = [UIColor lightGrayColor]; 
    } 
    else if ([ingredient.list isEqualToString:@"Shopping List"]) 
    { 
     cell.textLabel.textColor = [UIColor lightGrayColor]; 
    } 
    else 
    { 
     cell.textLabel.textColor = [UIColor blackColor]; 
    } 

} 
+1

Ich habe gerade Ihren Vorschlag umgesetzt. Es hat das Problem immer noch nicht gelöst. – TeaPow

+0

Ich wollte Hintergrundfarbe in meiner Zelle setzen und auf CellForRowAtIndexPath funktionierte es nicht, aber damit funktioniert es wie ein Zauber. Vielen Dank –

Verwandte Themen