I've noticed that depending when I call NSApp.runModal(for:)
, the table view contained in the presented window is unresponsive: it either doesn't scroll at all, or the content only updates after one or two seconds, presumably after the inertial scrolling has ended.
In the sample code below I call NSApp.runModal(for:)
in 3 different ways:
- with a direct call
- inside the callback to
perform(_:with:afterDelay:)
- inside the callback to
DispatchQueue.main.async
.
Only method 2 works. Why?
@main
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
let window = NSWindow(contentViewController: ViewController(nibName: nil, bundle: nil))
// 1. doesn't work
runModal(for: window)
// 2. works
// perform(#selector(runModal), with: window, afterDelay: 0)
// 3. doesn't work
// DispatchQueue.main.async {
// self.runModal(for: window)
// }
}
@objc func runModal(for window: NSWindow) {
NSApp.runModal(for: window)
}
}
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
override func loadView() {
let tableView = NSTableView()
tableView.addTableColumn(NSTableColumn())
tableView.dataSource = self
tableView.delegate = self
let scrollView = NSScrollView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
scrollView.documentView = tableView
view = scrollView
}
func numberOfRows(in tableView: NSTableView) -> Int {
return 100
}
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
return "\(row)"
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let cell = NSTableCellView()
cell.addSubview(NSTextField(labelWithString: "\(row)"))
return cell
}
}