Вопрос:

UITableView Обновить без прокрутки

ios objective-c uitableview

26794 просмотра

11 ответа

1515 Репутация автора

У меня есть _TableViewэлементы с элементами, и я хочу установить автоматическое обновление, и я не хочу, чтобы он прокручивался при обновлении, скажем, пользователь прокрутил 2 страницы вниз, и обновление сработало ->, поэтому я хочу поместить обновленное содержимое в верхняя часть таблицы, не прерывая прокрутку пользователя

Предположим, что пользователь был в строке 18, и теперь _dataSourceон обновляется, поэтому он выбирает, скажем, 4 элемента, поэтому я хочу, чтобы пользователь остался на элементе, которым он был.

Каков наилучший подход для достижения этого?

Автор: ColdSteel Источник Размещён: 31.08.2014 06:36

Ответы (11)


10 плюса

2859 Репутация автора

Решение

Я показываю, добавляется ли только одна строка. Вы можете расширить его до нескольких строк.

    // dataArray is your data Source object
    [dataArray insertObject:name atIndex:0];
    CGPoint contentOffset = self.tableView.contentOffset;
    contentOffset.y += [self tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    [self.tableView reloadData];
    [self.tableView setContentOffset:contentOffset];

Но чтобы это работало, вы должны определить - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPathметод. Или же, вы можете напрямую указать высоту строки таблицы, если она постоянна.

Автор: user1190882 Размещён: 31.08.2014 06:55

3 плюса

867 Репутация автора

Я делаю это так:

messages.insertContentsOf(incomingMsgs.reverse(), at: 0)
table.reloadData()

// This is for the first load, first 20 messages, scroll to bottom
if (messages.count <= 20) {
      let indexToScroll = NSIndexPath(forRow: saferSelf.messages.count - 1, inSection: 0)
      table.scrollToRowAtIndexPath(indexToScroll, atScrollPosition: .Top , animated: false)
}
// This is to reload older messages on top of tableview
else {
      let indexToScroll = NSIndexPath(forRow: incomingMsgs.count, inSection: 0)
      table.scrollToRowAtIndexPath(indexToScroll, atScrollPosition: .Top , animated: false)
      // Remove the refreshControl.height + tableHeader.height from the offset so the content remain where it was before reload
      let theRightOffset = CGPointMake(0, table.contentOffset.y - refreshControl.frame.height - table.headeView.frame.height)
      table.setContentOffset(theRightOffset, animated: false)
}

... также, поскольку я использую динамическую высоту ячейки, чтобы избежать некоторых странностей, оценка кэшируется:

var heightAtIndexPath = [NSIndexPath: CGFloat]()
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return heightAtIndexPath[indexPath] ?? UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    heightAtIndexPath[indexPath] = cell.frame.height
}
Автор: Marco M Размещён: 07.02.2016 03:06

22 плюса

647 Репутация автора

SWIFT 3

let contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.setContentOffset(contentOffset, animated: false)

Это ошибка iOS8 при использовании UITableViewAutomatic Dimension. Нам нужно сохранить смещение содержимого таблицы, перезагрузить таблицу, принудительно создать макет и вернуть contenOffset обратно.

CGPoint contentOffset = self.tableView.contentOffset;
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
[self.tableView setContentOffset:contentOffset];
Автор: Trung Phan Размещён: 17.02.2016 02:13

30 плюса

9878 Репутация автора

Для Swift 3+ :

Вам необходимо сохранить текущее смещение UITableView, затем перезагрузить и затем установить смещение обратно на UITableView.

Я создал эту функцию для этой цели:

func reload(tableView: UITableView) {

    let contentOffset = tableView.contentOffset
    tableView.reloadData()
    tableView.layoutIfNeeded()
    tableView.setContentOffset(contentOffset, animated: false)

}

Просто позвоните с помощью: reload(tableView: self.tableView)

Автор: David Seek Размещён: 29.10.2016 07:44

0 плюса

1 Репутация автора

попробуй заменить

reloadData с

tableView.reloadRows( at: tableView!.indexPathsForVisibleRows!, with: .none),

но вы должны быть осторожны no cells, если no cellsэтот метод должен вызвать сбой.

Автор: Jack Chen Размещён: 25.10.2017 06:24

0 плюса

59 Репутация автора

Когда вы хотите перезагрузить, вы должны

self.tableView.reloadData()

self.tableView.layoutIfNeeded()

а также использовать это UITableViewDelegate

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 'your maximum cell's height'
}

и ваш tableView останется на предыдущей позиции прокрутки без прокрутки

Автор: Apisteutos Размещён: 05.02.2018 02:04

1 плюс

21 Репутация автора

Этот код предотвратит ненужную анимацию и поддержит смещение содержимого представления прокрутки, он работал нормально для меня.

let lastScrollOffset = tableView.contentOffset
tableView.beginUpdates()
tableView.reloadData()
tableView.endUpdates()
tableView.layer.removeAllAnimations()
tableView.setContentOffset(lastScrollOffset, animated: false)
Автор: JhanviR Размещён: 22.02.2018 05:43

1 плюс

559 Репутация автора

Использовать расширение

создать UITableViewExtensions.swiftи добавить следующее:

extension UITableView {

    func reloadDataWithoutScroll() {
        let offset = contentOffset
        reloadData()
        layoutIfNeeded()
        setContentOffset(offset, animated: false)
    }
}
Автор: Yifan Размещён: 26.11.2018 07:48

0 плюса

1061 Репутация автора

Swift 4.2: простое решение

override func viewDidLoad() {
 super.viewDidLoad()

 self.tableView.estimatedRowHeight = 0
 self.tableView.estimatedSectionHeaderHeight = 0
 self.tableView.estimatedSectionFooterHeight = 0
}

//And then simply update(insert, reloadSections, delete etc) your tableView or reload

tableView.reloadData()

//or

UIView.performWithoutAnimation {

  tableView.beginUpdates()
  .....
  tableView.endUpdates()
}
Автор: ZAFAR007 Размещён: 08.03.2019 07:10

0 плюса

116 Репутация автора

В iOS 12.xиспользовании Xcode 10.2.1, более простой вариант.

UIView.performWithoutAnimation { 
    let loc = tableView.contentOffset
    tableView.reloadRows(at: [indexPath], with: .none)
    tableView.contentOffset = loc
}

Это работает лучше, чем следующее; он трясет время от времени, когда ряд не виден полностью.

let contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.setContentOffset(contentOffset, animated: false)
Автор: Pankaj Kulkarni Размещён: 12.05.2019 10:01

0 плюса

4183 Репутация автора

Просто установите estimatedRowHeightмаксимально возможное значение.

 self.tableView.estimatedRowHeight = 1000

Это оно!!

Автор: iMHitesh Surani Размещён: 13.06.2019 08:53
32x32