2009-06-10 6 views
0

Ich benutze ein UITableView, um die Auswahl eines (von vielen) Items zu ermöglichen. Ähnlich wie bei der UI, wenn ich einen Klingelton auswähle, möchte ich, dass das ausgewählte Element überprüft wird und die anderen nicht. Ich möchte die Zelle ausgewählt haben, wenn sie berührt wird, und dann wieder auf die normale Farbe animiert werden (wiederum wie die Klingeltonauswahl-Benutzeroberfläche).UITableView, Probleme beim Zubehörwechsel bei Auswahl

Eine UIViewController-Unterklasse ist der Delegat und die Datenquelle meiner Tabelle (nicht UITableViewController, da ich auch eine Symbolleiste darin habe).

Ich setze den AccessoryType der Zellen in CellForRowAtIndexPath :, und mein Modell aktualisiert, wenn Zellen in DidSelectRowAtIndexPath: ausgewählt sind. Die einzige Möglichkeit, die ausgewählte Zelle zum Häkchen zu setzen (und die vorherige zu löschen), besteht darin, [tableView reloadData] in didSelectRowAtIndexPath: aufzurufen. Wenn ich das mache, ist das Animieren der Zellabwahl seltsam (ein weißes Feld erscheint dort, wo das Label der Zelle sein sollte). Wenn ich reloadData nicht aufruft, wird der accessoryType natürlich nicht geändert, daher werden die Häkchen nicht angezeigt.

Ich nehme an, ich könnte die Animation ausschalten, aber das scheint lahm. Ich habe auch damit gespielt, die Zellen in didSelectRowAtIndexPath: zu bekommen und zu verändern, aber das ist ein großer Schmerz.

Irgendwelche Ideen? Abgekürzter Code folgt ...

+0

Ich habe aufgegeben und Animation ausgeschaltet, aber bearbeiten Kommentar des hatfinch hat den Trick. Ich hatte vorher mit dieser Lösung gespielt, aber es war mühsam, die anderen Zellen zu deaktivieren. Ich hatte nicht daran gedacht, den vorher ausgewählten Zellpfad zwischenzuspeichern, wie in Ron Srebo's Antwort. Danke euch beiden. – zpasternack

Antwort

4

Ich hatte genau dieses Problem und löste es nie.

Am Ende war es für mich, weil ich auf Änderungen im Modell hören musste (die Auswahl könnte sich außerhalb der Kontrolle des Benutzers ändern, wenn eine Verbindung verloren wurde), also änderte ich einfach das Modell und ließ die Benachrichtigung die Daten neu laden , aber es sah nicht so schön aus (es war wie eine nicht-animierte Abwahl, aber eine Durchlaufschleife Iteration spät!)

Ich vermute, der einzige Weg, es zu tun ist, wie Sie vorschlagen, einen Cache von Referenzen zu halten zu den Zellen selbst. Dies sollte nicht zu unordentlich sein, wenn Sie eine UITableViewCell-Unterklasse schreiben, um die Logik einzukapseln, und überschreiben -prepareForReuse.

Immer noch nicht hübsch, und wenn die Klingelton-Jungs bei Apple es so machen müssten, hätten sie das UITableView-Team härter drängen müssen, es zu reparieren!

EDIT:

Nun, was weißt du ?! Das ist wirklich sehr einfach. - [UITableView cellForRowAtIndexPath] gibt Ihnen die tatsächlichen Zellen (oder Null, wenn sie außerhalb des Bildschirms liegen) und Sie können nur den accessoryType ändern.

+0

Schreiben Sie einfach so in den didSelectRowAtIndexPath-Delegaten. [tableView deselectRowAtIndexPath: indexPath animiert: YES]; und [self.tableView reloadSections: [NSIndexSet indexSetWithIndex: indexPath.section] withRowAnimation: UITableViewRowAnimationAutomatic]; –

8

Ich löste es wie Hatfinch in seinem Schnitt vorgeschlagen. Mein Codebeispiel stellt sicher, dass nur eine Zeile überprüft wird, aber ich bin mir sicher, dass Sie es optimieren können, wenn das nicht das ist, was Sie brauchen.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 

int newRow = [indexPath row]; 
int oldRow = [lastIndexPath row]; 

if (newRow != oldRow) 
{ 
    UITableViewCell *newCell = [tableView cellForRowAtIndexPath: 
           indexPath]; 
    newCell.accessoryType = UITableViewCellAccessoryCheckmark; 

    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: 
           lastIndexPath]; 
    oldCell.accessoryType = UITableViewCellAccessoryNone; 

    lastIndexPath = indexPath; 
} 

[tableView deselectRowAtIndexPath:indexPath animated:YES]; 
} 
2

Ich habe eine sauberere Art, es zu tun.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 

    if (cell.accessoryType == UITableViewCellAccessoryNone) { 
     cell.accessoryType = UITableViewCellAccessoryCheckmark; 

    } else { 
     cell.accessoryType = UITableViewCellAccessoryNone; 
    } 
} 
+2

oh, und wie Sie das Häkchen aus der zuvor ausgewählten Zelle entfernen? –

+0

Das funktioniert perfekt für mich. –

1

Dies wird wie gewünscht arbeitet ...

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 


int newRow = [indexPath row]; 
int oldRow = [lastIndexPath row]; 


if (newRow == oldRow){ 
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 

    if (cell.accessoryType == UITableViewCellAccessoryNone) { 
     cell.accessoryType = UITableViewCellAccessoryCheckmark; 

    } else { 
     cell.accessoryType = UITableViewCellAccessoryNone; 
    } 

    lastIndexPath = indexPath; 
} 


if (newRow != oldRow) 
{ 
    UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath]; 
    newCell.accessoryType = UITableViewCellAccessoryCheckmark; 

    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastIndexPath]; 
    oldCell.accessoryType = UITableViewCellAccessoryNone; 

    lastIndexPath = indexPath; 
} 


[tableView deselectRowAtIndexPath:indexPath animated:YES]; 

} 
+0

Eine Erklärung Ihres Codes wird es viel nützlicher machen. – Ralgha

2

ich mit reloadRowsAtIndexPaths diesen einfachen und schönen Arbeitsmechanismus bin mit.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSArray *rowsArray = [NSArray arrayWithObjects:indexPath, selectedIndexPath, nil]; 
    self.selectedIndexPath = indexPath; 

    [tableView reloadRowsAtIndexPaths:rowsArray withRowAnimation:UITableViewRowAnimationNone]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 
    .... skipped usual code ..... 

    if ([selectedIndexPath compare:indexPath] == NSOrderedSame) { 
     cell.accessoryType = UITableViewCellAccessoryCheckmark; 
    } else { 
     cell.accessoryType = UITableViewCellAccessoryNone; 
    } 
    return cell; 
} 
+0

Das hat das Problem für mich komplett behoben. Danke vielmals. – Andrew

0
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:index]; 
    oldCell.accessoryType = UITableViewCellAccessoryNone; 
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
    cell.accessoryType = UITableViewCellAccessoryCheckmark; 
    index = indexPath; 
} 
Verwandte Themen