Swift macOS SegmentedControl Action没有被调用

时间:2019-01-17 15:00:39

标签: swift macos cocoa action nssegmentedcontrol

说明

我正在尝试使用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拥有。我无法想象   不管如何,我们都不会错过任何事情。

     
     

我实际上没有显示导航操作,因为我想   保持尽可能简单。而且动作没问题,   它完成了我想要的操作。如果我错了,请纠正我。


我在研究时发现的

可能的解决方案对我不起作用:


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

1 个答案:

答案 0 :(得分:0)

解决方案

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

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


背景

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

首先,调试用户界面表明问题绝对不在ViewHierarchy中。Debugging UI

因此,我尝试考虑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)没有将其操作发送到的目标。因此,它只能在响应者链中发送其操作方法-当第一个响应者位于另一个视图中时,该方法显然为零。