NSSTField和NSSegmentedControl在NSToolbar中

问题描述 投票:2回答:1

设置:

我正在使用故事板编写一个基于文档的应用程序,目标是OS X 10.11。主窗口有一个带有3段NSToolbarNSSegmentedControl。单击分段控件时,应该在水平或垂直NSSplitViewItem中切换NSSplitView的折叠状态。我试图实现的行为与Xcode 7中的相同,其中工具栏中的分段控件显示/隐藏Navigator / Debug Area / Utilities视图。

目前,分段控制向第一响应者发送动作。动作方法由NSSplitViewController子类实现,然后切换它的NSSplitViewItem的崩溃状态。

问题:

问题是工具栏还包含NSSearchField。如果NSSearchField具有焦点,或者即使分段控件本身具有焦点,单击带有光标的NSSegmentedControl也不会导致操作方法正确地使其成为NSSplitViewController子类的响应者链。

尝试的解决方案:

以前我使用通知而不是目标/操作解决了这个问题,但它最终变得过于复杂。另一个想法是将消息发送到窗口控制器,窗口控制器然后将其传递给它的内容视图控制器,该控制器将其传递给垂直分割视图控制器,然后该分割视图控制器将消息(如果需要)发送到水平分割视图控制器。虽然我知道这会起作用,但它似乎也是一个丑陋的解决方案,必须将代码添加到2个简单传递消息的附加文件中,我认为这是使用响应器链避免的。

任何见解将不胜感激。

最终解决方案

我意识到,如果关键视图上下文很重要,那么将分段控件的操作连接到第一个响应器只会有意义。在这种情况下,无论键视图是什么,分段控件都应在多个嵌套拆分视图中切换拆分视图项的折叠状态。

定义枚举以表示拆分视图的区域:

enum SplitViewArea : Int {
    // The raw values must match the order of the segmented control
    case left, top, right
}

定义协议以传达应切换拆分视图区域:

protocol SplitViewTogglable {
    func toggleSplitViewItem(matching area: SplitViewArea)
}

在窗口控制器中实现分段控制操作方法:

@IBAction func segmentedControlSelectionStateDidChange(_ sender: Any) {
    guard let segmentedControl = sender as? NSSegmentedControl else { return }
    guard let area = SplitViewArea(rawValue: segmentedControl.selectedSegment) else { return }
    guard let togglable = contentViewController as? SplitViewTogglable else { return }
    togglable.toggleSplitViewItem(matching: area)
}

在NSSplitViewController子类中实现SplitViewTogglable协议的方法:

func toggleSplitViewItem(matching area: SplitViewArea) {
    switch area {
    case .left:
        leftSplitViewItem.isCollapsed = !leftSplitViewItem.isCollapsed
    case .top:
        // Nested NSSplitViewController that adopts SplitViewTogglable
        if let togglable = centerSplitViewItem.viewController as? SplitViewTogglable {
            togglable.toggleSplitViewItem(matching: area)
        }
    case .right:
        rightSplitViewItem.isCollapsed = !rightSplitViewItem.isCollapsed
    }
}
swift macos nsviewcontroller nstoolbar nsstoryboard
1个回答
1
投票

NSSplitViewController被设置为窗口的contentViewController吗?作为响应者链搜索动作目标的一部分,如果窗口响应动作选择器,则窗口将其contentViewController视为补充目标。

当搜索字段具有关键焦点时,响应者链不会通过正常内容区域,而是通过工具栏到达窗口。因此,NSSplitViewController成为该搜索的一部分的唯一方法是成为contentViewController

© www.soinside.com 2019 - 2024. All rights reserved.