在视图控制器之间转换,OS X
Transitioning between view controller, OS X
我正在尝试编写一个 window 计时器应用程序,当用户按下开始按钮时,我希望它显示另一个带有倒计时等的视图控制器。我还在 Xcode,在那里我有一个连接开始按钮和第二个视图控制器的 segue。但是,只有三种不同的样式,即模态、sheet 和弹出。我想将 window 中的第一个视图控制器替换为第二个视图控制器。我找不到办法做到这一点。我尝试为 segue 使用自定义样式,并在其中使用 presentViewController: animator: 方法,但我不知道要发送什么作为 animator: 的参数。
在一个 window 中从一个视图控制器转换到另一个视图控制器的 simplest/proper 方法是什么,反之亦然?
同样在情节提要中,当我 select 一个视图控制器时,它显示了一个名为 "Presentation" 的属性,它可以是多个也可以是单个,它们代表什么?
我认为最简单的方法是交换 contentViewController
和 NSWindow
。
// in NSViewController's subclass
@IBAction func someAction(sender: AnyObject) {
let nextViewController = ... // instantiate from storyboard or elsewhere
if let window = view.window where window.styleMask & NSFullScreenWindowMask > 0 {
// adjust view size to current window
nextViewController.view.frame = CGRectMake(0, 0, window.frame.width, window.frame.height)
}
view.window?.contentViewController = nextViewController
}
这是选项 #1。
如果您想使用 segue,请创建自定义一个并将其设置为使用 IB 中的标识符进行 segue class。
class ReplaceSegue: NSStoryboardSegue {
override func perform() {
if let fromViewController = sourceController as? NSViewController {
if let toViewController = destinationController as? NSViewController {
// no animation.
fromViewController.view.window?.contentViewController = toViewController
}
}
}
}
这是选项 #2。
最后一个选项是使用 presentViewController:animator:
,共 NSViewController
。下面的代码是自定义 NSViewControllerPresentationAnimator
的溶解动画。
class ReplacePresentationAnimator: NSObject, NSViewControllerPresentationAnimator {
func animatePresentationOfViewController(viewController: NSViewController, fromViewController: NSViewController) {
if let window = fromViewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
fromViewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
viewController.view.alphaValue = 0
window.contentViewController = viewController
viewController.view.animator().alphaValue = 1.0
})
}
}
func animateDismissalOfViewController(viewController: NSViewController, fromViewController: NSViewController) {
if let window = viewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
viewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
fromViewController.view.alphaValue = 0
window.contentViewController = fromViewController
fromViewController.view.animator().alphaValue = 1.0
})
}
}
}
然后像这样呈现VC
@IBAction func replaceAction(sender: AnyObject) {
let nextViewController = ... // instantiate from storyboard or elsewhere
presentViewController(nextViewController, animator: ReplacePresentationAnimator())
}
要解雇,请在提交的 VC 中调用 presentingViewController
的 dismissViewController:
。
@IBAction func dismissAction(sender: AnyObject) {
presentingViewController?.dismissViewController(self)
}
Swift4 版本
class ReplacePresentationAnimator: NSObject, NSViewControllerPresentationAnimator {
func animatePresentation(of viewController: NSViewController, from fromViewController: NSViewController) {
if let window = fromViewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
fromViewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
viewController.view.alphaValue = 0
window.contentViewController = viewController
viewController.view.animator().alphaValue = 1.0
})
}
}
func animateDismissal(of viewController: NSViewController, from fromViewController: NSViewController) {
if let window = viewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
viewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
fromViewController.view.alphaValue = 0
window.contentViewController = fromViewController
fromViewController.view.animator().alphaValue = 1.0
})
}
}
}
希望对您有所帮助。
如果你有一个父视图控制器,你可以给它分配子视图控制器,并使用transition
方法。示例代码,放置在父视图控制器的viewDidLoad中:
if let firstController = self.storyboard?.instantiateController(withIdentifier: "firstController") as? NSViewController {
firstController.view.autoresizingMask = [.width, .height]
firstController.view.frame = self.view.bounds
self.addChild(firstController)
self.view.addSubview(firstController.view)
}
if let secondController = self.storyboard?.instantiateController(withIdentifier: "secondController") as? NSViewController {
self.addChild(secondController)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
if let firstController = self.children.first, let secondController = self.children.last {
self.transition(from: firstController, to: secondController, options: .crossfade, completionHandler: nil)
}
}
必须将第一个子控制器的视图作为子视图添加到父控制器的视图中,否则 transition
方法将不起作用。
在上面的示例中,一个故事板与一个主视图控制器(= self),一个具有故事板 ID "firstController', and another child view controller with storyboard ID "secondController'
的子视图控制器一起使用
我正在尝试编写一个 window 计时器应用程序,当用户按下开始按钮时,我希望它显示另一个带有倒计时等的视图控制器。我还在 Xcode,在那里我有一个连接开始按钮和第二个视图控制器的 segue。但是,只有三种不同的样式,即模态、sheet 和弹出。我想将 window 中的第一个视图控制器替换为第二个视图控制器。我找不到办法做到这一点。我尝试为 segue 使用自定义样式,并在其中使用 presentViewController: animator: 方法,但我不知道要发送什么作为 animator: 的参数。
在一个 window 中从一个视图控制器转换到另一个视图控制器的 simplest/proper 方法是什么,反之亦然?
同样在情节提要中,当我 select 一个视图控制器时,它显示了一个名为 "Presentation" 的属性,它可以是多个也可以是单个,它们代表什么?
我认为最简单的方法是交换 contentViewController
和 NSWindow
。
// in NSViewController's subclass
@IBAction func someAction(sender: AnyObject) {
let nextViewController = ... // instantiate from storyboard or elsewhere
if let window = view.window where window.styleMask & NSFullScreenWindowMask > 0 {
// adjust view size to current window
nextViewController.view.frame = CGRectMake(0, 0, window.frame.width, window.frame.height)
}
view.window?.contentViewController = nextViewController
}
这是选项 #1。
如果您想使用 segue,请创建自定义一个并将其设置为使用 IB 中的标识符进行 segue class。
class ReplaceSegue: NSStoryboardSegue {
override func perform() {
if let fromViewController = sourceController as? NSViewController {
if let toViewController = destinationController as? NSViewController {
// no animation.
fromViewController.view.window?.contentViewController = toViewController
}
}
}
}
这是选项 #2。
最后一个选项是使用 presentViewController:animator:
,共 NSViewController
。下面的代码是自定义 NSViewControllerPresentationAnimator
的溶解动画。
class ReplacePresentationAnimator: NSObject, NSViewControllerPresentationAnimator {
func animatePresentationOfViewController(viewController: NSViewController, fromViewController: NSViewController) {
if let window = fromViewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
fromViewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
viewController.view.alphaValue = 0
window.contentViewController = viewController
viewController.view.animator().alphaValue = 1.0
})
}
}
func animateDismissalOfViewController(viewController: NSViewController, fromViewController: NSViewController) {
if let window = viewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
viewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
fromViewController.view.alphaValue = 0
window.contentViewController = fromViewController
fromViewController.view.animator().alphaValue = 1.0
})
}
}
}
然后像这样呈现VC
@IBAction func replaceAction(sender: AnyObject) {
let nextViewController = ... // instantiate from storyboard or elsewhere
presentViewController(nextViewController, animator: ReplacePresentationAnimator())
}
要解雇,请在提交的 VC 中调用 presentingViewController
的 dismissViewController:
。
@IBAction func dismissAction(sender: AnyObject) {
presentingViewController?.dismissViewController(self)
}
Swift4 版本
class ReplacePresentationAnimator: NSObject, NSViewControllerPresentationAnimator {
func animatePresentation(of viewController: NSViewController, from fromViewController: NSViewController) {
if let window = fromViewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
fromViewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
viewController.view.alphaValue = 0
window.contentViewController = viewController
viewController.view.animator().alphaValue = 1.0
})
}
}
func animateDismissal(of viewController: NSViewController, from fromViewController: NSViewController) {
if let window = viewController.view.window {
NSAnimationContext.runAnimationGroup({ (context) -> Void in
viewController.view.animator().alphaValue = 0
}, completionHandler: { () -> Void in
fromViewController.view.alphaValue = 0
window.contentViewController = fromViewController
fromViewController.view.animator().alphaValue = 1.0
})
}
}
}
希望对您有所帮助。
如果你有一个父视图控制器,你可以给它分配子视图控制器,并使用transition
方法。示例代码,放置在父视图控制器的viewDidLoad中:
if let firstController = self.storyboard?.instantiateController(withIdentifier: "firstController") as? NSViewController {
firstController.view.autoresizingMask = [.width, .height]
firstController.view.frame = self.view.bounds
self.addChild(firstController)
self.view.addSubview(firstController.view)
}
if let secondController = self.storyboard?.instantiateController(withIdentifier: "secondController") as? NSViewController {
self.addChild(secondController)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
if let firstController = self.children.first, let secondController = self.children.last {
self.transition(from: firstController, to: secondController, options: .crossfade, completionHandler: nil)
}
}
必须将第一个子控制器的视图作为子视图添加到父控制器的视图中,否则 transition
方法将不起作用。
在上面的示例中,一个故事板与一个主视图控制器(= self),一个具有故事板 ID "firstController', and another child view controller with storyboard ID "secondController'
的子视图控制器一起使用