说明
我正在尝试使用NSSegmentedControls
在子ViewController之间过渡。 ParentViewController
位于Main.storyboard
中,而ChildViewControllers
位于Assistant.storyboard
中。每个ChildViewController都有一个细分控件,该细分控件分为2个细分,它们的主要用途是在ChildViewControllers之间导航。因此它们被设置为momentaryPushIn
而不是selectOne。每个ChildViewController使用 Delegate 与ParentViewController通信。
因此,在ParentViewController中,我添加了ChildViewControllers,如下所示:
/// The View of the ParentViewController configured as NSVisualEffectView
@IBOutlet var visualEffectView: NSVisualEffectView!
var assistantChilds: [NSViewController] {
get { return [NSViewController]() }
set(newValue) {
for child in newValue { self.addChild(child) }
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
addAssistantViewControllersToChildrenArray()
}
override func viewWillAppear() {
visualEffectView.addSubview(self.children[0].view)
self.children[0].view.frame = self.view.bounds
}
private func addAssistantViewControllersToChildrenArray() -> Void {
let storyboard = NSStoryboard.init(name: "Assistant", bundle: nil)
let exampleChild = storyboard.instantiateController(withIdentifier: "ExampleChild") as! ExampleChildViewController
let exampleSibling = storyboard.instantiateController(withIdentifier: "ExampleSibling") as! ExampleSiblingViewController
exampleChild.navigationDelegate = self
exampleSibling.navigationDelegate = self
assistantChilds = [exampleChild, exampleSibling]
}
到目前为止,一切都很好。 ExampleChildViewController
有一个NSTextField
实例。当我处于TextField范围内时,我可以触发SegmentedControls的操作。它应该向前和向后导航。但是,一旦离开TextField的范围,我仍然可以单击细分,但它们不会触发任何操作。即使TextField不是应用程序的当前“第一响应者”,他们也应该能够前后导航。我想我在这里遗漏了一些东西,希望任何人都可以帮助我。我知道问题不是NSSegmentedControl
,因为我在SiblingViewController中看到与配置为Switch / Checkbox的NSButton
相同的行为。我只是不知道我在做什么错。
这是我第一次在这里问自己一个问题,所以我希望我的工作方式对解决方案有所帮助。让我知道我是否可以做得更好/不同,或者是否需要提供有关某事的更多信息。
谢谢!
其他信息
出于完整性考虑:
ParentViewController
本身嵌入在ContainerView
中, 由RootViewController
拥有。我无法想象 不管如何,我们都不会错过任何事情。
我实际上没有显示导航操作,因为我想 保持尽可能简单。而且动作没问题, 它完成了我想要的操作。如果我错了,请纠正我。
可能的解决方案对我不起作用:
becomeFirstResponder
in its func viewWillAppear()
visualEffectView.addSubview(self.children[0].view, positioned: NSWindow.OrderingMode.above, relativeTo: nil
) 我在研究中发现的相关问题/主题:
答案 0 :(得分:0)
解决方案
let parentViewControllerInstance = self.parent as! ParentViewController
segmentedControl.target = parentViewControllerInstance
就我而言,我只需要将委托设置为sendAction
方法的目标即可。
背景
好吧,在阅读了数小时的AppKit文档之后,我现在可以回答我自己的问题了。
首先,调试用户界面表明问题绝对不在ViewHierarchy中。
因此,我尝试考虑NSButton和NSSegmentedControl的性质。在某些时候,我注意到这两个都是NSControl的子类。
class NSSegmentedControl : NSControl
class NSButton : NSControl
AppKit文档说:
讨论
按钮是用于在您的应用内启动操作的标准控件。您可以将按钮配置为具有多种不同的视觉样式,但是行为是相同的。 点击后,按钮将调用其关联目标对象的操作方法。 (...)您可以使用操作方法来执行特定于应用程序的任务。
粗体文本指向解决方案的关键-其相关目标对象的 。通常,我会定义一个控制项的操作,如下所示:
button.action = #selector(someFunc(_:))
这将导致NSControl实例调用此方法:
func sendAction(_ action: Selector?, to target: Any?) -> Bool
文档中的参数说明:
参数
动作
要在目标上调用的选择器。如果选择器为NULL,则不会发送任何消息。
目标
接收消息的目标对象。 如果对象为空,则应用程序在响应者链中搜索能够处理消息的对象。有关调度动作的更多信息,请参见NSActionCell的类描述。
总而言之,正在触发操作方法的NSControl实例(在我的情况下为NSSegmentedControl)没有将其操作发送到的目标。因此,它只能在响应者链中发送其操作方法-当第一个响应者位于另一个视图中时,该方法显然为零。