Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
516 views
in Technique[技术] by (71.8m points)

ios - How to prevent from scrolling UITableView up when NSFetchedResultsController add new record?

My UITableView is scrolling up once I add a new comment to CoreData. NSFetchedResultsController knows about it, puts this comment at the bottom of the table, and scroll table to top. Is it normal?

My example:

Just before I add a comment:

enter image description here

Just after I add a comment (not expected behavior):

enter image description here

It should be just like this (after I swipe it by hand manually):

enter image description here

This may be connected with following situation:

  1. This is sort descriptor of my NSFetchedResultsController:

    NSSortDescriptor(key: "createdAt", ascending: false) //from the latest to the oldest
    
  2. But I need to display my comments for reversed index paths (the latest are at the very bottom). In other words, everywhere when I need to use indexPath I use:

    private func reversedIndexPathForIndexPath(indexPath: NSIndexPath) -> NSIndexPath {
        return NSIndexPath(forRow: fetchedResultsController.fetchedObjects!.count - indexPath.row - 1, inSection: 0)
    }
    

NSFetchedResultsControllerDelegate:

//MARK: - NSFetchedResultsControllerDelegate

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

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

    switch type {
    case .Insert:
        if let newIndexPath = newIndexPath {
            tableView.insertRowsAtIndexPaths([reversedIndexPathForIndexPath(newIndexPath)], withRowAnimation: .Fade)
        }
    case .Delete:
        if let indexPath = indexPath {
            tableView.deleteRowsAtIndexPaths([reversedIndexPathForIndexPath(indexPath)], withRowAnimation: .Fade)
        }
    case .Update:
        if let indexPath = indexPath {
            tableView.reloadRowsAtIndexPaths([reversedIndexPathForIndexPath(indexPath)], withRowAnimation: .Fade)
        }
    case .Move:
        if let indexPath = indexPath, let newIndexPath = newIndexPath {
            tableView.deleteRowsAtIndexPaths([reversedIndexPathForIndexPath(indexPath)], withRowAnimation: .Fade)
            tableView.insertRowsAtIndexPaths([reversedIndexPathForIndexPath(newIndexPath)], withRowAnimation: .Fade)
        }
    }
}

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

Is it connected to my problem?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Edited answer:

I was able to reproduce this glitch with the following steps:

  1. UITableView with its rowHeight set to UITableViewAutomaticDimension and non-zero estimatedRowHeight.
  2. Table scrolled to its very bottom, with the last cell fully visible at the bottom margin.
  3. Inserting the new cell below the last one results in visual shift of the cells a few points down (in my setup it differs from 5 to 40).

The source of this behavior needs additional investigation.

For now the only solution is not to use UITableViewAutomaticDimension and return row heights from tableView:heightForRowAtIndexPath:.

By the way, implementation of inverted index paths has one significant flaw. When FRC calls it's delegate method controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:, all deletion index paths belongs to pre-change data set, and all insertion index paths - to post-change one. When you are in-beetween controllerWillChangeContent: and controllerDidChangeContent:, fetchedResultsController.fetchedObjects will contain post-change data set, i suppose (needs to be checked, though).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...