Error: UITableView jump to top with UITableViewAutomaticDimension

让人想犯罪 __ 提交于 2019-12-17 15:56:22

问题


I am using UITableView with estimatedRowHeight and UITableViewAutomaticDimension. Also I am using NSFetchedResultsControllerDelegate to reflect the changes.

Everything is work fine. Now the problem is when ever I add some record to CoreData, NSFetchedResultsController called the it's delegate but an unexpected things happen. TableView suddenly scroll to Top every time.

NSFetchedResultsControllerDelegate

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    tableView.beginUpdates()
}

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    tableView.endUpdates()
}

func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
        switch type {
        case .Insert:
            tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .None)
            break

        case .Update:
            tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .None)
            break

        case .Delete:
            tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .None)
            break

        default: break;
        }
    }

By googling I found few answers where people suggested to use tableView: heightForRowAtIndexPath: but as my cell height is dynamic. So what should I do?


回答1:


This is default behaviour of tableview, inserting an row in tableview scroll it to top. I did faced the same issue with my app. Here is how i able to manage the content offset of tableview, follow the steps,

1)Store the content offset of UITableview before inserting row or section.

2)Insert objects in array.

3)Reload the tableview

4)Subtract the difference and set the content offset manually.

let oldOffset: CGFloat = tblTest.contentSize.height
tblTest.reloadData()
let newOffset: CGFloat = tblTest.contentSize.height
tblTest.setContentOffset(CGPointMake(0, (newOffset - oldOffset)), animated: false)

This is how i have done in my applications so far, and with dynamic cell to overcome the reinitialise cell everytime, it is working just awesome.




回答2:


Adding to @jayesh-miruliya 's answer, in your NSFetchedResultsControllerDelegate after the switch statement, put this in your code:

tableView.reloadData()
dispatch_async(dispatch_get_main_queue(), {
    let topCellIndexPath = NSIndexPath(forRow: 0, inSection: 0)
    self. tableView.scrollToRowAtIndexPath(topCellIndexPath, atScrollPosition: .Top, animated: true)
})



回答3:


To solve my problem I save the cell height in the willDisplay method and in estimatedHeightForRowAt I'm retrieving the value.

var cellHeights = NSMutableDictionary()

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    if let height = cellHeights.object(forKey: indexPath) {
        return height as! CGFloat
    }

    return UITableViewAutomaticDimension
}

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



回答4:


tableView.reloadData()
if tableView.numberOfRowsInSection(0) > 0
{
      let indexPath = NSIndexPath(forRow: 0, inSection: 0)
      self. tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}



回答5:


  func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
    switch type {
    case .Insert:

      tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .None)
        break

    case .Update:
        tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .None)
        break

    case .Delete:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .None)
        break

    default: break;
    }
   tableView.reloadData()
  let indexPath = NSIndexPath(forRow: 0, inSection: 0)
  self. tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
   }

}



回答6:


let cou : Int = self.Array.count as Int
let lastindex : NSIndexPath = NSIndexPath(forRow: cou-1, inSection: 0)
self.TableName.scrollToRowAtIndexPath(lastindex, atScrollPosition: UITableViewScrollPosition.None, animated: true)

This code help you to scroll your tableview at particular position.




回答7:


func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    tabelView.reloadData()
}

this is work for me



来源:https://stackoverflow.com/questions/37001690/error-uitableview-jump-to-top-with-uitableviewautomaticdimension

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!