Zel*_*lko 3 xcode nsviewcontroller nsresponder swift macos-sierra
手头的问题是响应者链.根据Apple的说法:
此外,在macOS 10.10及更高版本中,视图控制器参与响应者链.NSViewController
如果我在macOS故事板中使用标准segue,则目标视图控制器的行为与预期一致 - 焦点,键等效,响应者链等.
但是,如果我使用自定义segue,目标视图控制器不会按预期运行:(具体而言,密钥等效项神秘地无法工作 - 但是,在测试中,来自源视图控制器的按钮上的等效键继续工作(这不是' t help/desired)
在macOS 10.12上,我使用以下自定义segue ...我做错了什么?
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)
}
}
Run Code Online (Sandbox Code Playgroud)
从我理解的方式来看,你的问题有四个部分:
我有以下示例与您的自定义segue类,关键等效示例,响应者链示例和焦点示例(假设您的意思是TextField焦点)正确运行.
正如您在下面的gif中看到的,您可以单击Segue按钮以使用您的PushSeguesegue 进行转换.然后单击" 关闭"按钮返回.右箭头和左箭头分别是Segue和Dismiss按钮的等效键.响应者链成功地将数据从SheetController(红色屏幕)传递到MainViewController(灰色屏幕).此外,textFields在segueing时正确聚焦.我将进一步详细解释每个功能.
我带PushAnimator了你发布的子类,并在视图中添加了一个红色背景,以便我可以直观地看到它.我通过在animatePresentation您的PushAnimator类的方法中添加以下行来完成此操作:
viewController.view.layer?.backgroundColor = CGColor.init(red: 1, green: 0, blue: 0, alpha: 1)
Run Code Online (Sandbox Code Playgroud)
该Segue公司按钮分配的keyEquivalent NSRightArrowFunctionKey和辞退按钮分配NSLeftArrowFunctionKey.您可以点击向右和向左箭头键在两个视图之间进行切换.要设置右箭头,我在MainViewController viewDidLoad()函数中添加了以下内容:
let array = [unichar(NSRightArrowFunctionKey)]
mainViewSegueButton.keyEquivalent = String(utf16CodeUnits: array, count: 1)
Run Code Online (Sandbox Code Playgroud)
要设置左箭头,我在SheetController viewDidLoad()函数中添加了以下内容:
let array = [unichar(NSLeftArrowFunctionKey)]
dismissButton.keyEquivalent = String(utf16CodeUnits: array, count: 1)
Run Code Online (Sandbox Code Playgroud)
既然你没有描述你对响应者链的具体问题,我只是实现了一个简单的测试,看看它是否有效.我将设置SheetController的dismissButton用的nextResponder MainViewController.我有以下中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
Run Code Online (Sandbox Code Playgroud)
为了解释上述内容:我首先dismissButton使用辅助功能标签进行设置,以便MainViewController稍后识别该按钮.将按钮的目标设置为nil意味着它将查看其nextResponder以处理它检测到的任何事件.我将按钮的动作设置为dismissAction方法,该方法在其中声明MainViewController.最后,我将dismissButtonnextResponder 设置为MainViewController.
回到后面MainViewController,我设置了dismissAction下面的方法.它只是增加一个计数器变量,并将该计数器与按钮的accessibilityLabel(我们之前设置的相同访问标签)一起显示到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!)
}
Run Code Online (Sandbox Code Playgroud)
为此,我假设您指的是textField焦点.在SheetController,我的sheetFocusTextField重点是viewDidAppear:
override func viewDidAppear() {
super.viewDidAppear()
sheetFocusTextField.becomeFirstResponder()
}
Run Code Online (Sandbox Code Playgroud)
在MainViewController,我mainFocusTextField关注的dismissAction方法:
mainFocusTextField.becomeFirstResponder()
Run Code Online (Sandbox Code Playgroud)
https://github.com/starkindustries/MacOSSegueTest
| 归档时间: |
|
| 查看次数: |
608 次 |
| 最近记录: |