【问题标题】:Swift macOS SegmentedControl Action not getting calledSwift macOS SegmentedControl 动作没有被调用
【发布时间】:2019-01-17 15:00:38
【问题描述】:

说明

我正在尝试使用NSSegmentedControls 在子视图控制器之间进行转换。 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,因为我在SiblingViewController 中看到NSButton 的行为相同,该NSButton 配置为开关/复选框。我只是不知道我做错了什么。

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

提前致谢!


其他信息

为了完整起见:

ParentViewController 本身嵌入在 ContainerView 中, 它归RootViewController 所有。我无法想象这会 无论如何都很重要,但这样我们就不会错过任何东西。


我实际上并没有显示导航动作,因为我想 尽可能简单。而且动作没问题, 它做我想做的事。如果我错了,请纠正我。


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


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

【问题讨论】:

    标签: swift macos cocoa action nssegmentedcontrol


    【解决方案1】:

    解决方案

    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 。

    【讨论】:

      猜你喜欢
      • 2017-05-10
      • 2019-07-24
      • 2015-03-30
      • 2015-01-31
      • 1970-01-01
      • 2015-03-07
      • 2015-05-17
      • 2015-10-21
      • 1970-01-01
      相关资源
      最近更新 更多