如何用Swift在NSAlert的accessoryView中嵌入NSTableView
问题原因
你的代码中所有自动布局约束都被注释,导致各级控件没有正确的尺寸和位置规则,无法正常渲染:
- 根容器view没有设置固定宽高,NSAlert无法正确计算accessoryView的占位大小
- scrollView没有和根容器view做约束绑定,尺寸无法正确适配父容器
- 单元格内的文本控件没有约束,不会显示内容
修正后完整代码
#!/usr/bin/env swift import AppKit import Foundation let app = NSApplication.shared app.setActivationPolicy(.regular) // 用于接收键盘输入且在程序坞显示 class TableViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource { var initialized = false let scrollView = NSScrollView(frame: NSRect(x: 0, y: 4, width: 200, height: 300)) let tableView = NSTableView(frame: NSRect(x: 0, y: 4, width: 200, height: 300)) override func loadView() { print("Load view") // 直接给根view设置初始尺寸 self.view = NSView(frame: NSRect(x: 0, y: 0, width: 200, height: 300)) } override func viewDidLoad() { print("Did load") super.viewDidLoad() setupView() setupTableView() } func setupView() { print("setupView") self.view.translatesAutoresizingMaskIntoConstraints = false // 给根view设置固定宽高 self.view.addConstraint(NSLayoutConstraint(item: self.view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200)) self.view.addConstraint(NSLayoutConstraint(item: self.view, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 300)) } func setupTableView() { print("setupTableView") self.view.addSubview(scrollView) self.scrollView.translatesAutoresizingMaskIntoConstraints = false // 绑定scrollView和父容器的四边约束 self.view.addConstraint(NSLayoutConstraint(item: self.scrollView, attribute: .left, relatedBy: .equal, toItem: self.view, attribute: .left, multiplier: 1.0, constant: 0)) self.view.addConstraint(NSLayoutConstraint(item: self.scrollView, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1.0, constant: 0)) self.view.addConstraint(NSLayoutConstraint(item: self.scrollView, attribute: .right, relatedBy: .equal, toItem: self.view, attribute: .right, multiplier: 1.0, constant: 0)) self.view.addConstraint(NSLayoutConstraint(item: self.scrollView, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1.0, constant: 0)) tableView.frame = scrollView.bounds tableView.delegate = self tableView.dataSource = self tableView.headerView = nil scrollView.backgroundColor = NSColor.clear scrollView.drawsBackground = false tableView.backgroundColor = NSColor.clear tableView.appearance = NSAppearance(named: NSAppearance.Name.vibrantDark) let col = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: "col")) col.minWidth = 200 tableView.addTableColumn(col) scrollView.documentView = tableView scrollView.hasHorizontalScroller = false scrollView.hasVerticalScroller = true tableView.reloadData() } func numberOfRows(in tableView: NSTableView) -> Int { return 100 } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { let text = NSTextField() text.stringValue = "Hello World \(row + 1)" let cell = NSTableCellView(frame: NSRect(x: 0, y: 0, width: 200, height: 20)) cell.addSubview(text) text.drawsBackground = false text.isBordered = false text.translatesAutoresizingMaskIntoConstraints = false // 打开文本控件的约束 cell.addConstraint(NSLayoutConstraint(item: text, attribute: .centerY, relatedBy: .equal, toItem: cell, attribute: .centerY, multiplier: 1, constant: 0)) cell.addConstraint(NSLayoutConstraint(item: text, attribute: .left, relatedBy: .equal, toItem: cell, attribute: .left, multiplier: 1, constant: 13)) cell.addConstraint(NSLayoutConstraint(item: text, attribute: .right, relatedBy: .equal, toItem: cell, attribute: .right, multiplier: 1, constant: -13)) return cell } func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { let rowView = NSTableRowView() rowView.isEmphasized = false return rowView } func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { return 22 } } func runOptionsDialog(args: [String]) { let title = args[0] let text = args[1] let okButton = args[2] let cancelButton = args[3] let a = NSAlert() a.messageText = title a.alertStyle = NSAlert.Style.warning a.informativeText = text a.addButton(withTitle: okButton) a.addButton(withTitle: cancelButton) let con = TableViewController() a.accessoryView = con.view app.activate(ignoringOtherApps: true) a.runModal() } runOptionsDialog(args:["title", "whast", "ok", "cancel"])
运行说明
直接执行swift table.swift即可看到弹窗中正常显示带滚动条的列表,100行带行号的文本可正常滚动查看。
内容的提问来源于stack exchange,提问作者Gabriel
相关产品推荐
相关产品推荐

