web-dev-qa-db-fra.com

Est-il possible d'actualiser une seule UITableViewCell dans une UITableView?

J'ai une coutume UITableView utilisant UITableViewCells . Chaque UITableViewCell a 2 boutons. Cliquer sur ces boutons changera une image dans une UIImageView dans la cellule.

Est-il possible d'actualiser chaque cellule séparément pour afficher la nouvelle image? .__ Toute aide est la bienvenue.

171
Wizard Of iOS

Une fois que vous avez le chemin indexPath de votre cellule, vous pouvez faire quelque chose comme:

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

Dans Xcode 4.6 et supérieur:

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

Vous pouvez bien sûr définir ce que vous voulez comme effet d'animation.

312
Romain

J'ai juste essayé d'appeler -[UITableView cellForRowAtIndexPath:], mais cela n'a pas fonctionné. Mais, ce qui suit fonctionne pour moi par exemple. alloc et release la NSArray pour une gestion de la mémoire restreinte.

- (void)reloadRow0Section0 {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
    [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
    [indexPaths release];
}
32
ma11hew28

Rapide:

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

    tableView.beginUpdates()
    tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
    tableView.endUpdates()
}
19
Esqarrouth

reloadRowsAtIndexPaths: est correct, mais force toujours les méthodes UITableViewDelegate à se déclencher.

L'approche la plus simple que je puisse imaginer est la suivante:

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

C'est important d'appeler votre implémentation configureCell: sur le thread principal, car cela ne fonctionnera pas sur un thread non-UI (la même histoire avec reloadData/reloadRowsAtIndexPaths:). Parfois, il peut être utile d’ajouter:

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

Il convient également d'éviter les travaux qui seraient effectués en dehors de la vue actuellement visible:

BOOL cellIsVisible = [[self.tableView indexPathsForVisibleRows] indexOfObject:indexPath] != NSNotFound;
if (cellIsVisible)
{
    ....
}
18
Maciek Czarnik

Si vous utilisez des TablesViewCells personnalisées, le générique

[self.tableView reloadData];    

ne répond pas efficacement à cette question sauf si vous quittez la vue actuelle et revenez. La première ne répond pas non plus.

Pour recharger avec succès votre première cellule de vue de tableau sans changer de vue , utilisez le code suivant:

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

Insérez la méthode refresh suivante qui appelle la méthode ci-dessus afin de ne pouvoir recharger que la cellule supérieure (ou la vue tableau entière si vous le souhaitez):

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

    //finish refreshing 
    [refreshControl endRefreshing];
}

Maintenant que vous avez trié cela, dans votre viewDidLoad, ajoutez ce qui suit:

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

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

[self.tableView addSubview:refreshControl];

Vous disposez maintenant d'une fonctionnalité de table d'actualisation personnalisée qui rechargera la cellule supérieure. Pour recharger la table entière, ajoutez le 

[self.tableView reloadData]; à votre nouvelle méthode d'actualisation. 

Si vous souhaitez recharger les données chaque fois que vous changez de vue, appliquez la méthode suivante:

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

Swift 3: 

tableView.beginUpdates()
tableView.reloadRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
6
ergunkocak

Juste pour mettre à jour légèrement ces réponses avec la nouvelle syntaxe littérale dans iOS 6, vous pouvez utiliser Paths = @ [indexPath] pour un seul objet ou Paths = @ [indexPath1, indexPath2, ...] pour plusieurs objets.

Personnellement, j’ai trouvé la syntaxe littérale des tableaux et des dictionnaires extrêmement utile et qui permet d’économiser beaucoup de temps. C'est simplement plus facile à lire, d'une part. Et cela supprime la nécessité d'un nil à la fin de toute liste multi-objets, qui a toujours été un bugaboo personnel. Nous avons tous nos éoliennes à incliner, oui? ;-)

Je pensais juste que je mettrais ceci dans le mélange. J'espère que ça aide.

4
Gregory Hill

J'ai besoin de la cellule de mise à niveau mais je veux fermer le clavier . Si j'utilise 

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

le clavier disparaît

0
user1784067