Можно ли обновить один UITableViewCell в UITableView?

182

У меня есть обычай, UITableViewиспользующий UITableViewCells. У каждого UITableViewCellесть 2 кнопки. Нажатие на эти кнопки изменит изображение UIImageViewвнутри ячейки.

Можно ли обновить каждую ячейку отдельно для отображения нового изображения? Любая помощь приветствуется.

Мастер iOS
источник

Ответы:

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
ОП ничего не анимировать, поэтому нет никакой необходимости называть начать / endupdates
KUBI
2
Пока метод не говорит, что устарел в последней общедоступной версии XCode, все версии iOS должны быть в порядке.
Алехандро Иван
1
@Supertecnoboff true, но в какой-то момент он может быть заменен или изменит свое поведение. Лучше обращаться с амортизацией как можно скорее
Алехандро Иван
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];
}
ma11hew28
источник
Нужен ли здесь [indexPaths release]? Я думал, что вам нужно только, если вы выделите объект самостоятельно.
powerj1984
4
Он выделил массив indexPaths. Но лучший вопрос заключается в том, почему он считает необходимым «жесткое управление памятью». Autorelease отлично справится с этой задачей.
Джон Кромарти
22

Swift:

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
источник
Где вызвать этот метод?
Мастер 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)
{
    ....
}
Maciek Czarnik
источник
Почему вы не хотите, чтобы делегат был вызван?
Kernix
Это лучший подход, поскольку он не заставляет представление таблицы полностью прокручиваться до вершины, в отличие от методов reloadRowsAtIndexPaths: или reloadData.
ZviBar
Я сделал это, и в итоге меня поймал тот факт, что камера была переработана
Traveling Man
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];
}
App Dev Guy
источник
6

Свифт 3:

tableView.beginUpdates()
tableView.reloadRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
ergunkocak
источник
4

Просто чтобы немного обновить эти ответы с помощью нового буквального синтаксиса в iOS 6 - вы можете использовать Paths = @ [indexPath] для одного объекта или Paths = @ [indexPath1, indexPath2, ...] для нескольких объектов.

Лично я обнаружил, что буквальный синтаксис для массивов и словарей чрезвычайно полезен и экономит время. С одной стороны, его легче читать. И это избавляет от нуля в конце любого списка нескольких объектов, который всегда был личной ошибкой. У всех нас есть свои ветряные мельницы, чтобы наклониться, да? ;-)

Просто думал, что я добавлю это в смесь. Надеюсь, поможет.

Грегори Хилл
источник
Скажите, Грег, что на самом деле является примером этого синтаксиса, пожалуйста? Спасибо!
Толстяк
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)
iphaaw
источник
0

Мне нужна ячейка обновления, но я хочу закрыть клавиатуру. Если я использую

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

клавиатура исчезнет


источник