Jer*_*jko 8 macos cocoa nstextfield nstableview swift
我有一个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
}
}
Run Code Online (Sandbox Code Playgroud)
这是Project上课
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"),
];
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢
这有点,在@Willeke 发布的副本中已经有一个答案,但是 1) 该答案在 Objective-C 中,而不是 Swift,2) 我可以提供更详细的答案(带图片!),以及 3)我'我厚颜无耻地追求赏金(收购规则#110)。因此,考虑到这一点,以下是我将如何实施您要执行的操作:
不要使用NSTextView; 使用NSTextField,甚至更好的NSSearchField. NSSearchField很棒,因为我们可以在 Interface Builder 中设置它,几乎不需要代码就可以创建过滤谓词。我们要做的就是NSPredicate在我们的视图控制器中创建一个属性,然后设置搜索字段的 Bindings Inspector 以指向它:
然后你可以创建一个数组控制器,它的过滤谓词绑定到相同的属性,它的Content Array绑定绑定到视图控制器上的一个属性:
而且,当然,将表视图绑定到数组控制器:
最后但并非最不重要的一点是,将表格单元格视图中的文本字段绑定到title属性:
有了 Interface Builder 中的所有设置,我们几乎不需要任何代码。我们需要的只是Project类的定义(所有属性都需要标记,@objc以便 Cocoa Bindings 系统可以看到它们):
class Project: NSObject {
@objc let title: String
init(title: String) {
self.title = title
super.init()
}
}
Run Code Online (Sandbox Code Playgroud)
我们还需要视图控制器上的项目属性、数组控制器和过滤谓词。过滤谓词需要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
}
Run Code Online (Sandbox Code Playgroud)
而且,最后但并非最不重要的是,我们的视图控制器上的扩展符合它NSSearchFieldDelegate(或者NSTextFieldDelegate如果您使用的是NSTextField代替NSSearchField),我们将在其上实现该control(:textView:doCommandBy:)方法。基本上,我们拦截搜索字段的字段编辑器正在执行的文本编辑命令,如果我们得到moveUp:或moveDown:,则返回true以告诉字段编辑器我们将处理这些命令。对于除这两个选择器之外的所有内容,返回false告诉字段编辑器执行它通常会执行的操作。
请注意,这就是您应该使用NSTextFieldorNSSearchField而不是NSTextView;的原因。这个委托方法只会NSControl被子类调用,而NSTextView不会。
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
瞧!
(当然,如果您更喜欢手动填充表格视图而不是使用绑定,您可以忽略大部分内容,只需实现control(:textView:doCommandBy:),手动更新您的表格选择,而不是要求您的数组控制器执行此操作。当然,使用绑定会导致结果用漂亮、干净的代码,这就是我更喜欢它的原因。)
| 归档时间: |
|
| 查看次数: |
620 次 |
| 最近记录: |