NSSplitViewItem折叠动画和窗口setFrame冲突

Teo*_*ori 7 multithreading core-animation nssplitview swift

我试图在移动其包含的窗口的同时制作一个(新的10.10)NSSplitViewItem崩溃和解体,以便将整个事物保持在"适当的位置".

问题是,我在动画中得到一个抽搐(如看到这里).

我正在进行折叠的代码是这样的:

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)
     }
}
Run Code Online (Sandbox Code Playgroud)

我知道"不要跨越流"问题(来自会话213,WWDC'13),其中在主线程上运行的窗口大小调整动画和在单独线程上运行的核心动画崩溃动画相互干扰.将splitViewItem折叠动画放到主线程上似乎是错误的方法,我有一种唠叨的感觉,有一个更好的方法来做到这一点,我错过了.

由于我没有在任何地方找到NSSplitViewItems的任何文档(还),我将不胜感激.

我已经在GitHub上的小测试项目在这里,如果有人想看看.

更新提到的项目现已更新解决方案.

谢谢,Teo

Tay*_*lor 13

问题类似于"不要跨越流"问题,因为您创建的动画有两个驱动程序:(1)拆分视图项(2)窗口,它们不同步.

在'13 Cocoa Animations talk的例子中,设置约束以产生正确的窗内动画,因为只有窗口的帧被动画化.

可以在这里尝试类似的东西 - 仅动画窗口的框架而不是分割视图项目,但由于项目管理用于(取消)折叠的约束,应用程序无法精确控制窗口内内容的动画:

动画窗框

相反,拆分视图项动画可以完全驱动动画,并使用NSWindow -anchorAttributeForOrientation:来描述窗口的框架是如何受到影响的.

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
}
Run Code Online (Sandbox Code Playgroud)

动画SplitViewItem