xcode 在视图控制器和 OS X 之间转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28454291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Transitioning between view controller, OS X
提问by user14492
I am trying to write a single window timer application, where when the user presses the start button I want it to show another view controller with countdown etc. I'm also using story board in Xcode, where I have got a segue which connects the start button and the second view controller. However, there are only three different styles i.e. modal, sheet, and pop-over. I want to replace the first view controller the second one in the window. I cannot find a way to do that. I tried using a custom style for the segue, and in that use presentViewController: animator: method but I cannot figure out what to send as the argument for the animator:.
我正在尝试编写一个单窗口计时器应用程序,当用户按下开始按钮时,我希望它显示另一个带有倒计时等的视图控制器。我还在 Xcode 中使用故事板,在那里我有一个连接开始按钮和第二个视图控制器。但是,只有三种不同的样式,即模态、表单和弹出窗口。我想将窗口中的第一个视图控制器替换为第二个视图控制器。我找不到办法做到这一点。我尝试为 segue 使用自定义样式,并在该样式中使用 presentViewController: animator: 方法,但我不知道要发送什么作为 animator: 的参数。
What is the simplest/proper way to transition from one view controller to the other in one window and vice versa?
在一个窗口中从一个视图控制器转换到另一个视图控制器的最简单/正确的方法是什么,反之亦然?
Also in the storyboard when I select a view controller it shows an attribute called "Presentation" which can be multiple and single, what do those represent?
同样在故事板中,当我选择一个视图控制器时,它会显示一个名为“Presentation”的属性,它可以是多个也可以是单个的,这些代表什么?
回答by bluedome
I think the simplest way is that swapping contentViewController
of NSWindow
.
我认为,最简单的方法就是交换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
}
This is option #1.
这是选项#1。
If you want to use segue, create custom one and set it to segue class with identifier in IB.
如果要使用segue,请创建自定义的并将其设置为带有IB 标识符的segue 类。
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
}
}
}
}
This is option #2.
这是选项#2。
Last option is using presentViewController:animator:
of NSViewController
. The code below is custom NSViewControllerPresentationAnimator
for dissolve animation.
最后一个选项是使用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
})
}
}
}
Then present VC like this.
然后像这样呈现VC。
@IBAction func replaceAction(sender: AnyObject) {
let nextViewController = ... // instantiate from storyboard or elsewhere
presentViewController(nextViewController, animator: ReplacePresentationAnimator())
}
For dismissal, call presentingViewController
's dismissViewController:
in the presented VC.
对于解雇,呼叫presentingViewController
的dismissViewController:
所呈现的VC。
@IBAction func dismissAction(sender: AnyObject) {
presentingViewController?.dismissViewController(self)
}
Swift4 Version
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
})
}
}
}
}
Hope this help.
希望这有帮助。
回答by Ely
If you have one parent view controller, you can assign child view controllers to it, and use the transition
method. Example code, to be placed in viewDidLoad of the parent view controller:
如果您有一个父视图控制器,则可以为其分配子视图控制器,并使用该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)
}
}
It's essential that the view of the first child controller is being added as sub view to the view of the parent controller, otherwise the transition
method doesn't work.
必须将第一个子控制器的视图作为子视图添加到父控制器的视图中,否则该transition
方法不起作用。
In the example above, a storyboard is used with one main view controller (= self), one child view controller with storyboard ID "firstController', and another child view controller with storyboard ID "secondController'
在上面的示例中,故事板与一个主视图控制器(= self)、一个故事板 ID 为“firstController”的子视图控制器和另一个故事板 ID 为“secondController”的子视图控制器一起使用