在 NSTextField 中输入时过滤 NSTable - 自动选择第一行

2024-04-17

我有一个NSTextView过滤的字段NSTable表作为用户在输入中键入的内容。我已经成功实现了表过滤。

现在,我的目标是自动选择第一个结果(表中的第一行),并允许用户在键入搜索查询时使用箭头键在结果之间移动。在表中的结果之间移动时,输入字段应保持焦点。 (这与 Spotlight 的工作原理类似)。

该应用程序现在的外观如下:

这是我的ViewController:

import Cocoa

class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate, NSTextFieldDelegate {

    @IBOutlet weak var field: NSTextField!
    @IBOutlet weak var table: NSTableView!

    var projects: [Project] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        projects = Project.all()

        field.delegate = self
        table.dataSource = self
        table.delegate = self
    }

    override func controlTextDidChange(_ obj: Notification) {
        let query = (obj.object as! NSTextField).stringValue

        projects = Project.all().filter { $0.title.contains(query) }

        table.reloadData()
    }

    func numberOfRows(in tableView: NSTableView) -> Int {
        return projects.count
    }

    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        if let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "FirstCell"), owner: nil) as? NSTableCellView {
            cell.textField?.stringValue = projects[row].title
            return cell
        }

        return nil
    }
}

这是Project class

struct Project {
    var title: String = ""

    static func all() -> [Project] {
        return [
            Project(title: "first project"),
            Project(title: "second project"),
            Project(title: "third project"),
            Project(title: "fourth project"),
        ];
    }
}

谢谢


这种情况,在 @Willeke 发布的副本中已经有一个答案,但是 1)这个答案是 Objective-C 中的,而不是 Swift,2)我可以提供一个更详细的答案(带图片!),3)我我正在厚颜无耻地追求赏金(获取规则#110)。因此,考虑到这一点,我将如何实现您想要做的事情:

不要使用NSTextView;使用一个NSTextField,或者更好的是,一个NSSearchField. NSSearchField非常棒,因为我们可以在 Interface Builder 中进行设置,几乎不需要任何代码即可创建过滤谓词。为此,我们所要做的就是创建一个NSPredicate属性在我们的视图控制器中,然后设置搜索字段的绑定检查器以指向它:

然后,您可以创建一个数组控制器,其过滤谓词绑定到同一属性,并且其Content Array绑定到视图控制器上的属性:

当然,将表视图绑定到数组控制器:

最后但并非最不重要的一点是将表格单元格视图中的文本字段绑定到title财产:

通过 Interface Builder 中的所有设置,我们几乎不需要任何代码。我们所需要的只是定义Project类(所有属性都需要标记@objc以便 Cocoa Bindings 系统可以看到它们):

class Project: NSObject {
    @objc let title: String

    init(title: String) {
        self.title = title
        super.init()
    }
}

我们还需要项目、数组控制器和过滤器谓词的视图控制器上的属性。过滤谓词需要是dynamic这样 Cocoa Bindings 可以在更改并更新 UI 时收到通知。如果projects可以改变,使之dynamic如此一来,对它的任何更改都会反映在 UI 中(否则,您可以摆脱dynamic就做到了@objc let).

class ViewController: NSViewController {
    @IBOutlet var arrayController: NSArrayController!

    @objc dynamic var projects = [
        Project(title: "Foo"),
        Project(title: "Bar"),
        Project(title: "Baz"),
        Project(title: "Qux")
    ]

    @objc dynamic var filterPredicate: NSPredicate? = nil
}

最后但并非最不重要的一点是,我们的视图控制器的扩展使其符合NSSearchFieldDelegate (or NSTextFieldDelegate如果你正在使用NSTextField而不是NSSearchField),我们将在其上实现control(:textView:doCommandBy:)方法。基本上,我们拦截搜索字段的字段编辑器执行的文本编辑命令,如果我们得到moveUp: or moveDown:, 返回true告诉字段编辑器我们将处理这些命令。对于除这两个选择器之外的所有内容,返回false告诉字段编辑器执行通常执行的操作。

请注意,这就是您应该使用NSTextField or NSSearchField而不是一个NSTextView;该委托方法只会被调用NSControl子类,其中NSTextView is not.

extension ViewController: NSSearchFieldDelegate {
    func control(_: NSControl, textView _: NSTextView, doCommandBy selector: Selector) -> Bool {
        switch selector {
        case #selector(NSResponder.moveUp(_:)):
            self.arrayController.selectPrevious(self)
            return true
        case #selector(NSResponder.moveDown(_:)):
            self.arrayController.selectNext(self)
            return true
        default:
            return false
        }
    }
}

Voilà!

(当然,如果您更喜欢手动填充表视图而不是使用绑定,则可以忽略其中大部分内容并只需实现control(:textView:doCommandBy:),手动更新表的选择,而不是要求阵列控制器执行此操作。当然,使用绑定会产生漂亮、干净的代码,这就是我更喜欢它的原因。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 NSTextField 中输入时过滤 NSTable - 自动选择第一行 的相关文章

随机推荐

  • 首先将外键映射到 EF 代码中的非主代理键列

    public class A DatabaseGenerated DatabaseGeneratedOption Identity public virtual int Aid get set public virtual ICollect
  • 选择元素时,CSS 中的插入符号 ^ 有何用途?

    我在文件中遇到了这样的 css 选择器 contactDetails ul li a a href tel 像这样的抑扬符 在 CSS 中没有定义的含义 两字符运算符 可用于属性选择器 http www w3 org TR selector
  • 使用字节将字母数字代码解码为键值对象

    我有一个来自 CS GO 游戏的 十字准线代码 CSGO O4Jsi V36wY rTMGK 9w7qF jQ8WB 我可以使用此函数解码一些值 import BigNumber from bignumber js Intentionall
  • Mongodb php查询,在数组中搜索?

    我正在寻找一种在具有以下结构的 answer 文档数组中搜索关键字 例如 Henrik 的方法 Array id gt MongoId Object id gt 4eeedd9545c717620a000007 formId gt 6 re
  • 使用纬度/经度计算从 A 点到线段的距离

    我正在开发一个使用 GPS 的 Android 应用程序 我想知道如果 新位置 C 点 距离线段 AB 太远 是否有办法可以丢弃 GPS 位置数据 我正在使用发现的点到线段公式在维基百科上 http en wikipedia org wik
  • 在MySQL php中将ID从一个表插入到另一个表

    我有两张桌子 一张是Information另一个是work force 信息 劳动力 当 的时候addInformation 接到电话 我想将数据插入到信息 以及id这是自动增量将插入表workForce 列 twf 这是我尝试过的 添加信
  • 在 BPMN 中用一个任务表示 while 循环的正确方法是什么?

    BPMN 中表示仅重定向到一个任务的简单 while 循环的正确方法是什么 我想说使用循环活动是更好的选择 因为它有助于保持流程模型整洁 在流程中创建循环时也要小心 因为任务定义通常在第一次迭代和第二次迭代之间发生变化 例如第一次迭代是创建
  • 如何使应用程序的触摸栏在 macOS 上始终可见?

    我正在做macOS 菜单栏应用程序 https vidr io显示全屏覆盖 用户可以通过菜单栏中的滑块控制该叠加层的不透明度 我希望将这些控件移至触摸栏 因为该应用程序用于屏幕录制 并且会记录主屏幕上的干扰 我的应用程序中的滑块应该像默认情
  • Spring Security 3.1.0 - 无法从 HTTPS 切换到 HTTP

    我是 Spring Security 的新手 所以我制作了一个小型 Web 应用程序 以便尝试它并找到对我正在从事的项目有用的配置 我强制通过 HTTPS 访问登录页面 登录后需要切换回 HTTP 换句话说 登录页面 仅限 HTTPS 其他
  • iPhone开发-设置UIWebView字体

    我必须显示从服务器提取的富文本 所以我使用 UIWebView 现在的问题是我无法控制 UIWebView 中使用的字体 如何更改字体以使用系统字体 使其与应用程序的其余部分一致 我现在正在做这样的事情 myRichTextView UIW
  • 如何在 AWS CloudWatch Insights 中按字段聚合日志,然后按 bin 聚合日志?

    我正在尝试执行一个查询 该查询将首先按字段计数聚合 然后按bin 1h 例如我想得到如下结果 Date Field Count 1 2019 01 01T10 00 00 000Z A 123 2 2019 01 01T11 00 00 0
  • 存档的 macOS 应用程序启动时显示空白窗口

    我有一个 macOS 应用程序 其中包含一个 ViewController 可以重命名应用程序窗口并调整其大小 有几个按钮 以及一个在启动时加载默认网页的 WKWebView 该项目本身是一个 xcworkspace 文件 因为它包含用于
  • 对外部程序的非阻塞调用,不会丢失返回码

    当从 Matlab 中启动外部程序 为了简洁起见 我们将其称为 EX 时 我可以这样做 status result system EX exe 它将阻塞直到 EX 返回 或者像这样 status result system start EX
  • 如何在winform和wpf中以编程方式实现鼠标移动、单击、右键单击和按键等?

    如何在 winform 和 wpf 中以编程方式移动鼠标 单击 右键单击和按键等 如果可能的话 请帮我提供代码片段 如果我正确理解你的问题 那么你想真正模拟输入 在这种情况下SendInput是要走的路 从这个链接 http robrely
  • 存储过程中的 SQL case 语句

    我有一个包含 CASE 语句的 SQL Server 存储过程 但是 如果多个条件成立 我需要附加这些值 因此 如果某个特定记录有失效日期 And 超出里程 我希望这两个值都显示在不可归档原因柱子 我将如何实现这一目标 CASE WHEN
  • 查找列表中不常见的元素

    我正在尝试编写一段可以自动分解表达式的代码 例如 如果我有两个列表 1 2 3 4 和 2 3 5 代码应该能够找到两个列表 2 3 中的公共元素 并组合其余的元素元素一起组成一个新列表 即 1 4 5 从这篇文章 如何找到列表交集 htt
  • Perl 6 语法与我认为的不匹配

    我正在做代码出现第 9 天 http adventofcode com 2017 day 9 您坐了一会儿并记录了流的一部分 您的谜题输入 这些字符代表组 开头的序列 并结束于 在一个组内 有零个或多个其他东西 用逗号分隔 要么是另一个组
  • Python 中检查两个冻结集是否相等的时间复杂度

    在网上找不到详细信息 当比较两个冻结集时 Python 是否会迭代其中一个集合中的元素 或者是否检查冻结集的哈希值 因为冻结集是可哈希的 由于参考文档对此没有任何说明 因此它依赖于实现 因此除了查看您正在使用的 Python 版本的源代码
  • Kotlin 中的变量,与 Java 的区别:“var”与“val”?

    我在尝试学习Kotlin https en wikipedia org wiki Kotlin programming language 什么是val var and internalKotlin 与 Java 相比 In Java Rad
  • 在 NSTextField 中输入时过滤 NSTable - 自动选择第一行

    我有一个NSTextView过滤的字段NSTable表作为用户在输入中键入的内容 我已经成功实现了表过滤 现在 我的目标是自动选择第一个结果 表中的第一行 并允许用户在键入搜索查询时使用箭头键在结果之间移动 在表中的结果之间移动时 输入字段