使用NSView.layoutSubtreeIfNeeded()动画自动布局约束不适用于macOS High Sierra

时间:2017-11-14 10:16:18

标签: cocoa autolayout macos-high-sierra nsanimationcontext nsanimation

我有一个基本的Mac应用程序,通过自动布局完成视图动画:

  • 我在当前视图的右侧添加了一个新视图
  • 我更新了约束,以便新视图最终填满窗口

→动画将使其看起来好像视图从右侧滑入。

为自动布局更改设置动画的推荐方法是:

  1. 更新约束
  2. 使用NSAnimationContext.runAnimationGroup()
  3. 在动画块内设置allowsImplicitAnimationtrue
  4. 在动画块内调用view.layoutSubtreeIfNeeded()
  5. 我遵循了这个建议,在macOS Sierra上一切正常,但在macOS High Sierra上,动画不再发生了。相反,视图显示在没有动画的最终位置。

    我找到了一种解决方法:我使用DispatchQueue.main.async在下一个runloop循环中安排动画。然而,这似乎是一个黑客,我想知道在这里是否还有其他东西。

    这是我的实际代码:

    private func appendSlideViewControllerAnimated(_ viewController:NSViewController, to viewToTheLeft:NSView)
    {
        // Insert the new view on the very right, just outside the parent:
    
        viewController.view.frame = self.view.bounds
        viewController.view.translatesAutoresizingMaskIntoConstraints = false
    
        view.addSubview(viewController.view)
    
        viewController.view.topAnchor.constraint(     equalTo: view.topAnchor     ).isActive = true
        viewController.view.bottomAnchor.constraint(  equalTo: view.bottomAnchor  ).isActive = true
    
        viewController.view.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    
        viewController.view.leadingAnchor.constraint(equalTo: viewToTheLeft.trailingAnchor).isActive = true
    
        // Update the layout after we just added the view on the right: 
        view.layoutSubtreeIfNeeded()
    
        // Starting with macOS High Sierra, animating constraint changes for the newly inserted view
        // only works if scheduled on the next runloop:
        //DispatchQueue.main.async {
    
    
             // Update the constraints to pin the view to the left:
    
            self.view.removeConstraint(self.activeSlideLeadingConstraint!)
    
            self.activeSlideLeadingConstraint = viewController.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor)
            self.activeSlideLeadingConstraint?.constant = 0
            self.activeSlideLeadingConstraint?.isActive = true
    
            NSAnimationContext.runAnimationGroup( { context in
    
                self.isAnimating = true
    
                context.duration = self.slidingAnimationDuration
                context.allowsImplicitAnimation = true
    
    
                self.view.layoutSubtreeIfNeeded()
    
            }, completionHandler: {
    
                viewToTheLeft.removeFromSuperview()
    
                self.clearUndoHistory()
    
                self.updateFirstResponder()
    
                self.isAnimating = false
            })
        //}
    }
    

1 个答案:

答案 0 :(得分:0)

为您尝试设置动画的根视图启用核心动画支持。它可以在Interface Builder中完成,也可以通过编程方式完成:

override func viewDidLoad()
{
    super.viewDidLoad()
    view.wantsLayer = true
}
相关问题