Чи можливо оновити один UITableViewCell в UITableView?


182

У мене є звичай , UITableViewвикористовуючи UITableViewCellс. У кожній UITableViewCellє 2 кнопки. Натискання цих кнопок змінить зображення в UIImageViewмежах клітинки.

Чи можливо оновити кожну клітинку окремо для відображення нового зображення? Будь-яка допомога вдячна.

Відповіді:


323

Коли у вас з'явиться indexPath своєї комірки, ви можете зробити щось на кшталт:

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

У Xcode 4.6 і вище:

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

Ви, звичайно, можете встановити що завгодно, як ефект анімації.


4
Тут мимоволі, але звичайно, якби ви оновлювали лише одну клітинку, яку, напевно, хотіли б використати [NSArray arrayWithObject:]замість цього.
Лев Кассарані

57
Крім того, у цій ситуації beginUpdatesі endUpdatesє непотрібними.
кубі

2
ОП нічого не анімує, тому немає потреби телефонувати на початок / ендупдад
kubi

2
Поки метод не каже застарілим в останній загальнодоступній версії Xcode, всі версії iOS повинні бути добре.
Алехандро Іван

1
@Supertecnoboff правда, але в якийсь момент його можна замінити або змінити свою поведінку. Краще впоратися зі знищеннями
Алехандро Іван

34

Я спробував просто зателефонувати -[UITableView cellForRowAtIndexPath:], але це не вийшло. Але, наприклад, для мене працює наступне. Я allocі для жорсткого управління пам'яттю.releaseNSArray

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

Чи потрібна тут [indexPaths release]? Я думав, що тобі це потрібно лише, якщо ти сам призначиш об'єкт.
powerj1984

4
Він виділив масив indexPaths. Але краще питання, чому він вважає необхідним "жорстке управління пам'яттю". Автореліз буде робити цю роботу ідеально добре.
Джон Кромарті

22

Швидкий:

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

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

Куди закликати цей метод?
Master AgentX

18

reloadRowsAtIndexPaths:це нормально, але все-таки змусить UITableViewDelegateметоди обстрілювати.

Найпростіший підхід, який я можу собі уявити:

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

Це важливо , щоб викликати вашу configureCell:реалізацію на основний потік, так як вона не буде роботи на НЕ-UI потоці (та ж історія з reloadData/ reloadRowsAtIndexPaths:). Іноді може бути корисно додати:

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

Варто також уникати роботи, яка проводилася б поза поточним видимим видом:

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

Чому б ви не хотіли викликати делегата?
kernix

Це найкращий підхід, оскільки він не змушує перегляд таблиці прокручувати до вершини на відміну від методів reloadRowsAtIndexPaths: або reloadData.
ZviBar

Я зробив це, і мене впіймало те, що клітина була перероблена
Мандрівна людина

16

Якщо ви використовуєте власні TableViewCells, загальні

[self.tableView reloadData];    

не дає ефективної відповіді на це питання, якщо ви не залишите поточний погляд і не повернетесь назад. Ні перша відповідь не дає.

Для успішного перезавантаження першої комірки подання таблиці без перемикання поглядів використовуйте наступний код:

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

Вставте наступний метод оновлення, який викликає вищевказаний метод, щоб ви могли користувальницьку перезавантажувати лише верхню клітинку (або все подання таблиці, якщо бажаєте):

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

    //finish refreshing 
    [refreshControl endRefreshing];
}

Тепер, коли ви їх відсортували, всередині viewDidLoadдодайте наступне:

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

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

[self.tableView addSubview:refreshControl];

Тепер у вас є спеціальна функція таблиці оновлення, яка перезавантажить верхню комірку. Щоб перезавантажити всю таблицю, додайте

[self.tableView reloadData]; до вашого нового методу оновлення.

Якщо ви хочете перезавантажувати дані щоразу, коли перемикаєте представлення даних, застосуйте метод:

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

6

Швидкий 3:

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

4

Просто, щоб трохи оновити ці відповіді новим синтаксисом буквального в iOS 6 - ви можете використовувати Paths = @ [indexPath] для одного об’єкта, або Paths = @ [indexPath1, indexPath2, ...] для декількох об'єктів.

Особисто я виявив, що буквальний синтаксис для масивів та словників є надзвичайно корисним та значно заощаджує час. Це просто простіше для читання. І це знімає потребу в нулі в кінці будь-якого списку об'єктів, який завжди був особистим бугабу. У всіх нас є вітряні млини, так? ;-)

Просто думав, що кину це в суміш. Сподіваюся, це допомагає.


Скажи Грег, що насправді є прикладом цього синтаксису? Дякую!
Fattie

3

Ось розширення UITableView із 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()
    }

}

Подзвоніть з

self.tableView.updateRow(row: 1)

0

Мені потрібна комірка для оновлення, але я хочу закрити клавіатуру. Якщо я користуюся

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

клавіатура зникає

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.