NSSplitViewItem - анимация свертывания и конфликт оконного набора.

Я пытаюсь сделать (новый в 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)
     }
}

Мне известна проблема "Не пересекать потоки" (из сеанса 213, WWDC'13), когда анимация изменения размера окна, работающая в главном потоке, и анимация свертывания основной анимации, работающая в отдельном потоке, мешают друг другу. Помещение анимации коллапса splitViewItem в основной поток кажется неправильным подходом, и у меня возникает неприятное ощущение, что есть гораздо лучший способ сделать это, которого я пропускаю.

Поскольку нигде (пока) я не нахожу никакой документации по NSSplitViewItems, я был бы признателен за любую информацию по этому вопросу.

У меня есть небольшой тестовый проект на GitHub, если кто-то хочет посмотреть.

Обновление Упомянутый проект был обновлен с помощью решения.

Спасибо, Тео

2 ответа

Решение

Проблема похожа на проблему "не пересекать потоки" в том, что для созданной вами анимации есть два драйвера: (1) элемент разделенного вида (2) окна, и они не синхронизированы.

В примере из выступления 13 "Какао-анимация" были установлены ограничения, чтобы обеспечить правильную анимацию внутри окна, поскольку анимировался только кадр окна.

Нечто подобное можно попробовать здесь - только анимация рамки окна, а не разделение элемента представления, но, поскольку элемент управляет ограничениями, используемыми для (не) свертывания, приложение не может точно контролировать, как анимируется содержимое в окне:

Анимация оконной рамы

Вместо этого анимация элемента разделенного вида может полностью управлять анимацией и использовать NSWindow's -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
}

Анимация SplitViewItem

Для тех, кто использует Цель C и нацелен на 10.11 El Capitan. Это помогло мне, не нужно было устанавливать AnchorAttributes.

splitViewItem.collapsed = YES;
Другие вопросы по тегам