NSSplitViewItem collapse animation and window setFrame conflicting
core-animation, multithreading, nssplitview, swift
Solution
The problem is similar to the "don't cross the streams" issue in that there are two drivers to the animation you've created: (1) the split view item (2) the window, and they're not in sync.
In the example from the '13 Cocoa Animations talk, constraints were setup to result in the correct within-window animation as only the window's frame was animated.
Something similar could be tried here -- only animating the window's frame and not the split view item, but since the item manages the constraints used to (un)collapse, the app can't control exactly how within-window content animates:
Instead the split view item animation could completely drive the animation and use NSWindow's `-anchorAttributeForOrientation:` to describe how the window's frame is affected.
if let splitViewItem = self.splitViewItems[panelID] as? NSSplitViewItem {
let window = self.view.window
if panelID == 0 {
// The Trailing edge of the window is "anchored", alternatively it could be the Right edge
window.setAnchorAttribute(.Trailing, forOrientation:.Horizontal)
}
splitViewItem.animator().collapsed = !splitViewItem.collapsed
}
Problem
I am trying to make a (new in 10.10) NSSplitViewItem collapse and uncollapse whilst moving its containing window so as to keep the whole thing "in place". The problem is that I am getting a twitch in the animation (as seen here). The code where I'm doing the collapsing is this: ``` func togglePanel(panelID: Int) { if let splitViewItem = self.splitViewItems[panelID] as? NSSplitViewItem { // Toggle the collapsed state NSAnimationContext.runAnimationGroup({ context in // special case for the left panel if panelID == 0 { var windowFrame = self.view.window.frame let panelWidth = splitViewItem.viewController.view.frame.width if splitViewItem.collapsed { windowFrame.origin.x -= panelWidth windowFrame.size.width += panelWidth } else { windowFrame.origin.x += panelWidth windowFrame.size.width -= panelWidth } self.view.window.animator().setFrame(windowFrame, display: true) } splitViewItem.animator().collapsed = !splitViewItem.collapsed }, completionHandler: nil) } } ``` I am aware of the "Don't cross the streams" issue (from session 213, WWDC'13) where a window resizing animation running on the main thread and a core animation collapse animation running on a separate thread interfere with each other. Putting the splitViewItem collapse animation onto the main thread seems like the wrong approach and I've got a nagging feeling there's a much better way of doing this that I'm missing. Since I am not finding any documentation on the NSSplitViewItems anywhere (yet) I would appreciate any insights on this. I have the little test project on GitHub here if anyone wants a look. Update The project mentioned has now been updated with the solution. Thanks, Teo