手头的问题是响应者链。根据Apple的说法:
此外,在macOS 10.10及更高版本中,视图控制器参与 在响应者链中。 NSViewController
如果我在macOS情节提要中使用标准segue ,则目标视图控制器的行为与预期相同 - 焦点,等效键,响应者链等。
但是,如果我使用自定义segue ,则目标视图控制器的行为不符合预期:(具体而言,密钥等效项无法正常工作 - 但是,在测试中,来自来源视图控制器的按钮上的等效键继续工作(这不是有用/不需要的)
在macOS 10.12上,我使用了以下自定义信号......我做错了什么?
class PushSegue: NSStoryboardSegue {
override func perform() {
(sourceController as AnyObject).presentViewController(destinationController as! NSViewController, animator: PushAnimator())
}
}
class PushAnimator: NSObject, NSViewControllerPresentationAnimator {
func animatePresentation(of viewController: NSViewController, from fromViewController: NSViewController) {
viewController.view.wantsLayer = true
viewController.view.frame = CGRect(x: fromViewController.view.frame.size.width, y: 0,
width: fromViewController.view.frame.size.width, height: fromViewController.view.frame.size.height)
fromViewController.addChildViewController(viewController)
fromViewController.view.addSubview(viewController.view)
let futureFrame = CGRect(x: 0, y: 0, width: viewController.view.frame.size.width,
height: viewController.view.frame.size.height)
NSAnimationContext.runAnimationGroup({ context in
context.duration = 0.75
viewController.view.animator().frame = futureFrame
}, completionHandler:nil)
}
func animateDismissal(of viewController: NSViewController, from fromViewController: NSViewController) {
let futureFrame = CGRect(x: viewController.view.frame.size.width, y: 0,
width: viewController.view.frame.size.width, height: viewController.view.frame.size.height)
NSAnimationContext.runAnimationGroup({ context in
context.duration = 0.75
context.completionHandler = {
viewController.view.removeFromSuperview()
viewController.removeFromParentViewController()
}
viewController.view.animator().frame = futureFrame
}, completionHandler: nil)
}
}
答案 0 :(得分:8)
从我理解的方式来看,你的问题有四个部分:
我让以下示例正确运行自定义segue类,等效键示例,响应者链示例和< strong>焦点示例(假设您的意思是TextField焦点)。
正如您在下面的gif中所看到的,您可以点击 Segue 按钮,使用您的PushSegue
segue进行转换。然后点击关闭按钮返回。右箭头和左箭头分别是 Segue 和 Dismiss 按钮的等效键。响应者链成功地将数据从SheetController
(红色屏幕)传递到MainViewController
(灰色屏幕)。此外,textFields在segueing时正确聚焦。我将进一步详细解释每个功能。
我带了您发布的PushAnimator
子类,只是在视图中添加了红色背景,以便我可以直观地看到它。我是通过在animatePresentation
类的PushAnimator
方法中添加以下行来完成此操作的:
viewController.view.layer?.backgroundColor = CGColor.init(red: 1, green: 0, blue: 0, alpha: 1)
Segue 按钮被指定为NSRightArrowFunctionKey
的等效键,关闭按钮被指定为NSLeftArrowFunctionKey
。您可以点击向右和向左箭头键在两个视图之间进行切换。要设置右箭头,我在MainViewController
viewDidLoad()
函数中添加了以下内容:
let array = [unichar(NSRightArrowFunctionKey)]
mainViewSegueButton.keyEquivalent = String(utf16CodeUnits: array, count: 1)
要设置左箭头,我在SheetController
viewDidLoad()
函数中添加了以下内容:
let array = [unichar(NSLeftArrowFunctionKey)]
dismissButton.keyEquivalent = String(utf16CodeUnits: array, count: 1)
由于您没有描述您对响应者链的具体问题,我只是实施了一个简单的测试,看看它是否有效。我将SheetController
的{{1}}设置为dismissButton
的nextResponder。我在MainViewController
的{{1}}:
SheetController
要解释上述内容:我首先使用辅助功能标签设置viewDidLoad()
,以便// SheetController viewDidLoad()
// Set Accessibility Label
dismissButton.setAccessibilityLabel("DismissButton")
// Set button target and action
dismissButton.target = nil
dismissButton.action = #selector(MainViewController.dismissAction(_:))
// Set nextResponder
dismissButton.nextResponder = self.parent
稍后可以识别该按钮。将按钮的目标设置为nil意味着它将查看其nextResponder以处理它检测到的任何事件。我将按钮的操作设置为dismissButton
方法,该方法在MainViewController
内声明。最后,我将dismissAction
的nextResponder设置为MainViewController
。
回到dismissButton
,我在下面设置了MainViewController
方法。它只是增加一个计数器变量,并将该计数器与按钮的accessibilityLabel(我们之前设置的相同访问标签)一起显示到textField。最后一行驳回了MainViewController
。
dismissAction
为此,我假设您指的是textField焦点。在SheetController
中,我// MainViewController
func dismissAction(_ sender: AnyObject) {
counter += 1
let buttonAccessLabel = (sender as! NSButton).accessibilityLabel()
helloWorldTextField.stringValue = "Action #" + counter.description + " from: " + buttonAccessLabel!
self.dismissViewController(self.presentedViewControllers!.first!)
}
焦点在SheetController
:
sheetFocusTextField
在viewDidAppear
中,override func viewDidAppear() {
super.viewDidAppear()
sheetFocusTextField.becomeFirstResponder()
}
方法有MainViewController
个焦点:
mainFocusTextField
https://github.com/starkindustries/MacOSSegueTest