2

I have developed a macOS personal finance app in SwiftUI that uses NSTableViews and NSOutlineViews through the NSViewControllerRepresentable interface between SwiftUI and AppKit.

I have found that the AppKit view capabilities are far superior to anything I can create using SwiftUI lists plus they run faster and support TypeSelect. Passing data into the Appkit ViewControllers is straightforward but getting information out seems to be less so.

Apple developer documentation suggests that I should use a Coordinator class and I have tried to do so but to no avail. The delegated method that I need (func tableViewSelectionDidChange(_ notification: Notification)) fails to run (from inside my Coordinator class).

For the moment I am exchanging data and actions using NotificationCenter.default and that is working well but I am keen to use the 'official' method. I have found a macOS application that uses Coordinator successfully (at https://www.markusbodner.com/til/2021/02/08/multi-line-text-field-with-swiftui-on-macos/), but I cannot get my Coordinator class to work as a NSTableViewDelegate even though it builds and runs without errors (Xcode 12.4).

All I want to do for a start is to get an NSViewController that contains a NSTableView to pass the NSTableView.selectedRow into its parent SwiftUI view via a Coordinator, whenever the user selects a new row in the NSTableView. Can anyone help (with some sample code, if possible, please)?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65

1 Answers1

0

I seem to have found the solution to my own problem. I had been allocating my NSTableViewDelegate to the Coordinator in the makeNSViewController function. However, it appears that my NSTableView is not being instantiated until the code that populates the contents of my NSTableView's NSTableViewDataSource has been run (in the updateNSViewController function). As a result there is no NSTableViewDelegate to allocate.

Moving tableVC.tableView?.delegate = context.coordinator into the updateNSViewController function, following the code that populates the contents of my NSTableViewDataSource, makes my NSTableViewDelegate work as intended and tableView.selectedRow values are now passed to my parent SwiftUI view via func tableViewSelectionDidChange(_ notification: Notification) successfully. Hurrah!

It may be useful to note that I am using Cocoa bindings in my NSTableView and have found that it is necessary to leave empty @IBAction func stubs (ctrl-dragged form Interface Builder as normal) in the ViewController (the File's Owner) and place copies of those funcs (populated with code, of course) in my Coordinator class to get their code to execute as intended.

The resulting overall code is much neater than my old code, which used notifications to pass actions and data between SwiftUI and AppKit - so the 'official' method looks to be best.