Multithreading NSSplitViewItem折叠动画和窗口设置帧冲突

Multithreading NSSplitViewItem折叠动画和窗口设置帧冲突,multithreading,core-animation,swift,nssplitview,Multithreading,Core Animation,Swift,Nssplitview,我试图在移动其包含窗口的同时(在10.10中新增)使NSSplitViewItem折叠和解折叠,以使整个内容保持“到位” 问题是我在动画中出现了抽搐(如图所示) 我进行折叠的代码如下: func togglePanel(panelID: Int) { if let splitViewItem = self.splitViewItems[panelID] as? NSSplitViewItem { // Toggle the collapsed state

我试图在移动其包含窗口的同时(在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)
     }
}
我知道“不要跨流”问题(来自WWDC'13第213次会议),其中主线程上运行的窗口大小调整动画和单独线程上运行的核心动画折叠动画相互干扰。将splitViewItem折叠动画放在主线程上似乎是错误的方法,我有一种烦人的感觉,有一种做这件事的更好的方法,我错过了

由于我还没有在任何地方找到关于NSSplitViewItems的任何文档,我希望您能对此有所了解

如果有人想看的话,我在GitHub上有一个小测试项目

更新上述项目现在已使用解决方案更新

谢谢,
Teo

该问题类似于“不要跨流”问题,因为您创建的动画有两个驱动因素:(1)分割视图项(2)窗口,它们不同步

在'13 Cocoa Animations talk中的示例中,设置了约束以生成正确的窗口内动画,因为只有窗口的帧设置了动画

在这里也可以尝试类似的方法——只设置窗口框架的动画,而不设置分割视图项的动画,但由于该项管理用于(取消)折叠的约束,因此应用程序无法准确控制窗口内内容的动画方式:

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

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
}

适用于任何使用目标C和瞄准10.11 El Capitan的人。 这对我来说是个好办法,不需要设置主持人

splitViewItem.collapsed = YES;

太好了,谢谢你。很好的清晰答案和切中要害的解决方案。在这种情况下,也不需要将折叠动画包装在一个组中。是的,但它不会更改窗口大小。(Swift 3.0)