Ist es möglich, eine einzelne UITableViewCell in einer UITableView zu aktualisieren?

182

Ich habe einen Brauch UITableViewmit UITableViewCells. Jeder UITableViewCellhat 2 Tasten. Durch Klicken auf diese Schaltflächen wird ein Bild in einer UIImageViewZelle geändert .

Ist es möglich, jede Zelle einzeln zu aktualisieren, um das neue Bild anzuzeigen? Jede Hilfe wird geschätzt.

Assistent von iOS
quelle

Antworten:

323

Sobald Sie den Indexpfad Ihrer Zelle haben, können Sie Folgendes tun:

[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPathOfYourCell, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates]; 

In Xcode 4.6 und höher:

[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:@[indexPathOfYourCell] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates]; 

Sie können natürlich einen beliebigen Animationseffekt festlegen.

Romain
quelle
4
Nitpicking hier, aber natürlich, wenn Sie nur eine einzelne Zelle aktualisieren würden, würden Sie wahrscheinlich [NSArray arrayWithObject:]stattdessen verwenden wollen.
Leo Cassarani
57
Auch in dieser Situation sind die beginUpdatesund endUpdatesunnötig.
Kubi
2
Das OP animiert nichts, so dass es nicht nötig ist, die begin / endupdates aufzurufen
kubi
2
Solange die Methode in der letzten öffentlichen Xcode-Version nicht als veraltet bezeichnet wird , sollten alle iOS-Versionen in Ordnung sein.
Alejandro Iván
1
@Supertecnoboff stimmt, aber irgendwann könnte es ersetzt werden oder wird sein Verhalten ändern. Es ist besser, mit Abschreibungen so schnell wie möglich umzugehen
Alejandro Iván
34

Ich habe versucht, nur anzurufen -[UITableView cellForRowAtIndexPath:], aber das hat nicht funktioniert. Aber das Folgende funktioniert zum Beispiel für mich. Ich allocund releasedie NSArrayfür enge Speicherverwaltung.

- (void)reloadRow0Section0 {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
    [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
    [indexPaths release];
}
ma11hew28
quelle
Ist hier [indexPaths release] notwendig? Ich dachte, Sie brauchen das nur, wenn Sie das Objekt selbst zuweisen.
powerj1984
4
Er hat das indexPaths-Array zugewiesen. Die bessere Frage ist jedoch, warum er eine "enge Speicherverwaltung" für notwendig hält. Autorelease wird den Job hier perfekt machen.
John Cromartie
22

Schnell:

func updateCell(path:Int){
    let indexPath = NSIndexPath(forRow: path, inSection: 1)

    tableView.beginUpdates()
    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
    tableView.endUpdates()
}
Esqarrouth
quelle
Wo soll man diese Methode aufrufen?
Master AgentX
18

reloadRowsAtIndexPaths:ist in Ordnung, wird aber dennoch UITableViewDelegateMethoden zum Feuern zwingen .

Der einfachste Ansatz, den ich mir vorstellen kann, ist:

UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
[self configureCell:cell forIndexPath:indexPath];

Es ist wichtig , dass Sie Ihre configureCell:Implementierung im Hauptthread aufrufen , da sie im Nicht-UI-Thread nicht funktioniert (dieselbe Geschichte mit reloadData/ reloadRowsAtIndexPaths:). Manchmal kann es hilfreich sein, Folgendes hinzuzufügen:

dispatch_async(dispatch_get_main_queue(), ^
{
    [self configureCell:cell forIndexPath:indexPath];
});

Es lohnt sich auch, Arbeiten zu vermeiden, die außerhalb der derzeit sichtbaren Ansicht ausgeführt werden:

BOOL cellIsVisible = [[self.tableView indexPathsForVisibleRows] indexOfObject:indexPath] != NSNotFound;
if (cellIsVisible)
{
    ....
}
Maciek Czarnik
quelle
Warum soll der Delegierte nicht angerufen werden?
Kernix
Dies ist der beste Ansatz, da die Tabellenansicht im Gegensatz zu den Methoden reloadRowsAtIndexPaths: oder reloadData nicht gezwungen wird, ganz nach oben zu scrollen.
ZviBar
Ich tat dies und wurde von der Tatsache überrascht, dass die Zelle recycelt wurde
Travelling Man
16

Wenn Sie benutzerdefinierte TableViewCells verwenden, wird die generische

[self.tableView reloadData];    

beantwortet diese Frage nur dann effektiv, wenn Sie die aktuelle Ansicht verlassen und zurückkehren. Die erste Antwort auch nicht.

Verwenden Sie den folgenden Code, um Ihre erste Tabellenansichtszelle erfolgreich neu zu laden, ohne die Ansicht zu wechseln :

//For iOS 5 and later
- (void)reloadTopCell {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
    [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
}

Fügen Sie die folgende Aktualisierungsmethode ein, die die obige Methode aufruft, damit Sie nur die oberste Zelle (oder die gesamte Tabellenansicht, falls gewünscht) neu laden können:

- (void)refresh:(UIRefreshControl *)refreshControl {
    //call to the method which will perform the function
    [self reloadTopCell];

    //finish refreshing 
    [refreshControl endRefreshing];
}

Nachdem Sie dies sortiert haben, viewDidLoadfügen Sie in Ihrem Bereich Folgendes hinzu:

//refresh table view
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];

[refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];

[self.tableView addSubview:refreshControl];

Sie haben jetzt eine benutzerdefinierte Funktion zum Aktualisieren von Tabellen, mit der die oberste Zelle neu geladen wird. Fügen Sie zum erneuten Laden der gesamten Tabelle die hinzu

[self.tableView reloadData]; zu Ihrer neuen Aktualisierungsmethode.

Wenn Sie die Daten bei jedem Ansichtswechsel neu laden möchten, implementieren Sie die folgende Methode:

//ensure that it reloads the table view data when switching to this view
- (void) viewWillAppear:(BOOL)animated {
    [self.tableView reloadData];
}
App Dev Guy
quelle
6

Swift 3:

tableView.beginUpdates()
tableView.reloadRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
Ergunkocak
quelle
4

Um diese Antworten mit der neuen Literal-Syntax in iOS 6 leicht zu aktualisieren, können Sie Paths = @ [indexPath] für ein einzelnes Objekt oder Paths = @ [indexPath1, indexPath2, ...] für mehrere Objekte verwenden.

Persönlich habe ich festgestellt, dass die wörtliche Syntax für Arrays und Wörterbücher äußerst nützlich ist und viel Zeit spart. Zum einen ist es einfach einfacher zu lesen. Und es macht eine Null am Ende jeder Liste mit mehreren Objekten überflüssig, was schon immer ein persönlicher Bugaboo war. Wir haben alle unsere Windmühlen zum Kippen, ja? ;-);

Ich dachte nur, ich würde das in die Mischung werfen. Ich hoffe es hilft.

Gregory Hill
quelle
Sagen Sie Greg, was ist eigentlich ein Beispiel für diese Syntax dort, bitte? Vielen Dank!
Fattie
3

Hier ist eine UITableView-Erweiterung mit Swift 5:

import UIKit

extension UITableView
{    
    func updateRow(row: Int, section: Int = 0)
    {
        let indexPath = IndexPath(row: row, section: section)

        self.beginUpdates()
        self.reloadRows(at: [indexPath as IndexPath], with: UITableView.RowAnimation.automatic)
        self.endUpdates()
    }

}

Rufen Sie an mit

self.tableView.updateRow(row: 1)
iphaaw
quelle
0

Ich brauche die Upgrade-Zelle, möchte aber die Tastatur schließen. Wenn ich benutze

let indexPath = NSIndexPath(forRow: path, inSection: 1)
tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
tableView.endUpdates()

Die Tastatur verschwindet


quelle