Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSTableView animation inconsistant

I have a NSTableView which intermittently will stop animating and updating itself correctly, leading to a terrible user experience.

let oldRows = filteredDocuments
let newRows = newFilteredDocuments
let diff = oldRows.diff(newRows)
filteredDocuments = newFilteredDocuments

if (diff.results.count > 0) {
    let deletionIndexPaths = NSMutableIndexSet()
    diff.deletions.forEach { deletionIndexPaths.addIndex($0.idx) }
    let insertionIndexPaths = NSMutableIndexSet()
    diff.insertions.forEach { insertionIndexPaths.addIndex($0.idx) }

    self.tableView?.beginUpdates()
    self.tableView?.removeRowsAtIndexes(deletionIndexPaths, withAnimation: NSTableViewAnimationOptions.EffectFade)
    self.tableView?.insertRowsAtIndexes(insertionIndexPaths, withAnimation: NSTableViewAnimationOptions.SlideLeft)
    self.tableView?.endUpdates()
}

There seems to be no logic to when it stops animating, and in the many tests I've done it feels almost like it's build related. Interestingly it never stops animating when I am profiling...

It's as if something on the main thread is clogging up the UI and then the NSTableView times out and cancels the update - but I have no idea how I can debug this.

like image 411
Chris Avatar asked Apr 20 '16 00:04

Chris


1 Answers

How about if you do one and then the other? I just recently did something similar when I needed to insert a cell AND scroll, which lead to a poor user experience. The solution was to add a slight delay. Not sure if this is what you're trying to accomplish base on the small code snippet, but here we go:

let oldRows = filteredDocuments
let newRows = newFilteredDocuments
let diff = oldRows.diff(newRows)
filteredDocuments = newFilteredDocuments

if (diff.results.count > 0) {
    let deletionIndexPaths = NSMutableIndexSet()
    diff.deletions.forEach { deletionIndexPaths.addIndex($0.idx) }
    let insertionIndexPaths = NSMutableIndexSet()
    diff.insertions.forEach { insertionIndexPaths.addIndex($0.idx) }

    self.tableView?.beginUpdates()
    self.tableView?.removeRowsAtIndexes(deletionIndexPaths, withAnimation: NSTableViewAnimationOptions.EffectFade)
    self.tableView?.endUpdates()

    let delay = 0.35
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))) // Hate this syntax
    dispatch_after(delay, dispatch_get_main_queue(), { [weak self] in
        self?.tableView?.beginUpdates()
        self?.tableView?.insertRowsAtIndexes(insertionIndexPaths, withAnimation: NSTableViewAnimationOptions.SlideLeft)
        self?.tableView?.endUpdates()
    })
}
like image 99
Doug Mead Avatar answered Nov 03 '22 19:11

Doug Mead