scrollToRowAtIndexPath всегда прокручивается сверху вместо текущего смещения

В моем UITableView Я использую метод для прокрутки до последней ячейки:

WLNetworkClient.sharedClient().createCommentWIthText(commentTextView.text, forItem: item) { error in

    defer {
        UIAlertController.showAlertFromError(error)
    }

    if error == nil {
        self.fetchedResultsController.fetchRequest.fetchLimit += 1
        try! self.fetchedResultsController.performFetch()
        self.tableView.reloadData()
        self.scrollTableViewToBottom()
    }
}

private func scrollTableViewToBottom() {

    tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: fetchedResultsController.fetchedObjects!.count - 1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)
}

но это не работает, как ожидается, потому что таблица ВСЕГДА прокручивается сверху, даже если я нахожусь на второй ячейке, чтобы продлиться. Как это исправить?

5 ответов

Ответ досдос у меня сработал в Swift 2 Добавление с незначительным обновлением

Объявить ивар

var heightAtIndexPath = NSMutableDictionary()

в func viewDidLoad()

func viewDidLoad() {
  .... your code
  self.tableView.rowHeight = UITableViewAutomaticDimension
}

Затем добавьте следующие 2 метода:

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
   let height = self.heightAtIndexPath.objectForKey(indexPath)
   if ((height) != nil) {
     return CGFloat(height!.floatValue)
   } else {
    return UITableViewAutomaticDimension
   }
 }

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
  let height = cell.frame.size.height
  self.heightAtIndexPath.setObject(height, forKey: indexPath)
}

SWIFT 3:

var heightAtIndexPath = NSMutableDictionary()

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    let height = self.heightAtIndexPath.object(forKey: indexPath)
    if ((height) != nil) {
        return CGFloat(height as! CGFloat)
    } else {
        return UITableViewAutomaticDimension
    }
}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let height = cell.frame.size.height
    self.heightAtIndexPath.setObject(height, forKey: indexPath as NSCopying)
}

Расширение ZaEeM ZaFaR отличный ответ:

Цель С

NSMutableDictionary *heightAtIndexPath;
heightAtIndexPath = [[NSMutableDictionary alloc] init];

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSNumber *height = [heightAtIndexPath objectForKey:indexPath];
    if(height) {
        return height.floatValue;
    } else {
        return UITableViewAutomaticDimension;
    }
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    [heightAtIndexPath setObject:@(cell.frame.size.height) forKey:indexPath];
}

Эта проблема покрыта здесь: Как узнать, когда UITableVIew завершил ReloadData?

Измените свой код на:

self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.scrollTableViewToBottom()

LayoutIfNeeded заставляет перезагрузку таблицы происходить немедленно. Все объяснено в ссылке.

Чтобы быть более быстрым, я бы упростил версию Swift 3, представленную выше:

    var heightAtIndexPath = [IndexPath: CGFloat]()

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        if let height = self.heightAtIndexPath[indexPath] {
            return height
        }
        return UITableViewAutomaticDimension
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        let height = cell.frame.size.height
        self.heightAtIndexPath[indexPath] = height
    }

Я думаю, что проблема в том, что вы прокручиваете перед обновлением tableView (по self.tableView.reloadData()). Попробуйте отложить прокрутку:

     dispatch_async(dispatch_get_main_queue()) {
         self.scrollTableViewToBottom()
    }

Или принудительно обновите tableView:

    self.tableView.reloadData()
    self.tableView.layoutIfNeeded()
    self.scrollTableViewToBottom()
Другие вопросы по тегам