1

描述

我正在尝试使用NSSegmentedControls子 ViewControllers 之间的转换。ParentViewController位于Main.storyboardChildViewControllers位于Assistant.storyboard。_ 每个 ChildViewController 都有一个 SegmentedControl,分为 2 个 Segment,它们的主要用途是在 ChildViewController 之间导航。因此它们被设置为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 的范围,我仍然可以单击 Segments,但它们不会触发任何操作。即使 TextField 不是应用程序的当前“第一响应者”,它们也应该能够向前和向后导航。我想我在这里遗漏了一些东西,我希望任何人都可以帮助我。我知道问题不是NSSegmentedControl因为我NSButton在 SiblingViewController 中看到配置为 Switch/Checkbox 的相同行为。我只是不知道我做错了什么。

这是我第一次在这里自己提出问题,所以我希望我的做法能够很好地解决问题。让我知道我是否可以做得更好/不同,或者我是否需要提供有关某事的更多信息。

提前致谢!


附加信息

为了完整起见:

ParentViewController本身嵌入在 a中,由ContainerView拥有RootViewController。我无法想象这有什么关系,但这样我们就不会错过任何东西。


我实际上并没有显示导航操作,因为我想让它尽可能简单。此外,这个动作没有问题,它做我想做的事。如果我对此有误,请纠正我。


我在研究时发现的可能解决方案,但对我不起作用:


我在研究时发现的相关问题/主题:

4

1 回答 1

0

解决方案

let parentViewControllerInstance = self.parent as! ParentViewController
segmentedControl.target = parentViewControllerInstance

就我而言,我只需要将委托设置为sendAction方法的目标。


背景

好的,在阅读 AppKit 文档数小时后,我现在可以回答我自己的问题了。

首先,调试 UI 表明问题肯定不在 ViewHierarchy 中。调试界面

所以我试着去思考NSButton和NSSegmentedControl的本质。在某些时候,我注意到两者都是 NSControl 的子类。

class NSSegmentedControl : NSControl
class NSButton : NSControl

AppKit 文档说:

讨论

按钮是用于在您的应用程序中启动操作的标准控件。您可以配置具有许多不同视觉样式的按钮,但行为是相同的。单击时,按钮会调用其关联目标对象的操作方法。(...) 您使用 action 方法来执行特定于应用程序的任务。

粗体文本指向解决方案的关键——与其关联的目标对象。通常我定义一个控制项的动作是这样的:

button.action = #selector(someFunc(_:))

这会导致 NSControl 实例调用它:

func sendAction(_ action: Selector?, to target: Any?) -> Bool

文档中的参数说明:

参数

那个行动

在目标上调用的选择器。如果选择器为 NULL,则不发送任何消息。

目标

接收消息的目标对象。如果对象为 nil,则应用程序在响应者链中搜索能够处理消息的对象。有关调度操作的更多信息,请参阅 NSActionCell 的类描述。

总之,触发动作方法的 NSControl 实例(在我的例子中是 NSSegmentedControl)没有目标可以发送动作。所以它只能通过响应者链发送它的动作方法——当第一响应者位于另一个视图中时,这显然是 nil 。

于 2019-01-17T20:20:06.837 回答