What is NSViewControllerRepresentable
In SwiftUI, there are no View Controllers, only Views. So what should we do if want to use something related to View Controllers? Here comes NSViewControllerRepresentable/UIViewControllerRepresentable. Basically, we can use instance of View Controller Representable as View, contains a view controller.
Since view controllers have their own view, ViewControllerRepresentable has not view body.
protocol NSViewControllerRepresentable : View where Self.Body == Never
A Simple Sample of NSViewControllerRepresentable
- Create a new SwiftUI app.
 - Add a new file, choose Cocoa Class, name it as TextViewController.swift.
Choose create xib file as well. - Add a close button and label.
 

- TextViewController.swift
 
//
//  TextViewController.swift
//  ViewControllerRepresentable Test
//
//  Created by zhaoxin on 2022/6/12.
//
import Cocoa
class TextViewController: NSViewController {
    @IBOutlet weak var label: NSTextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func closeButtonClicked(_ sender: Any) {
        self.dismiss(sender)
    }
}
- TextView
 
//
//  TextView.swift
//  ViewControllerRepresentable Test
//
//  Created by zhaoxin on 2022/6/12.
//
import AppKit
import SwiftUI
struct TextView:NSViewControllerRepresentable {
    func makeNSViewController(context: Context) -> TextViewController {
        let controller  = TextViewController()        
        return controller
    }    
    
    func updateNSViewController(_ nsViewController: TextViewController, context: Context) {
    }
}
- ContentView.swift
 
//
//  ContentView.swift
//  ViewControllerRepresentable Test
//
//  Created by zhaoxin on 2022/6/12.
//
import SwiftUI
struct ContentView: View {
    @State var title = ""
    @State var showTextView = false
    
    var body: some View {
        HStack {
            TextField("Title", text: $title)
        
            Button("Show Text View") {
                showTextView = true
            }
            .sheet(isPresented: $showTextView) {
                TextView()
            }
        }
        .padding()
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
The app ran as below, but the close button didn't work.

Coordinator
View Controllers are class, and View Representables are structs. We use Coordinator to pass changes to SwiftUI.
- TextView
 
//  ViewControllerRepresentable Test
//
//  Created by zhaoxin on 2022/6/12.
//
import AppKit
import SwiftUI
struct TextView:NSViewControllerRepresentable {
    @Environment(\.presentationMode) var presentationMode
    @Binding var title:String
    
    class Coordinator: NSObject, TextViewControllerDelegate {
        var parent: TextView
        init(_ parent: TextView) {
            self.parent = parent
        }
        
        func textView(_ tvc: TextViewController) {
            self.parent.presentationMode.wrappedValue.dismiss()
        }
    }
    
    func makeNSViewController(context: Context) -> TextViewController {
        let controller  = TextViewController()
        controller.delegate = context.coordinator
        
        return controller
    }
    
    func updateNSViewController(_ nsViewController: TextViewController, context: Context) {
        nsViewController.label.stringValue = title
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
}
- TextViewController
 
//
//  TextViewController.swift
//  ViewControllerRepresentable Test
//
//  Created by zhaoxin on 2022/6/12.
//
import Cocoa
class TextViewController: NSViewController {
    @IBOutlet weak var label: NSTextField!
    weak var delegate:TextViewControllerDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func closeButtonClicked(_ sender: Any) {
        delegate?.textView(self)
    }
}
protocol TextViewControllerDelegate:AnyObject {
    func textView(_ textView:TextViewController)
}
- ContentView
 
//
//  ContentView.swift
//  ViewControllerRepresentable Test
//
//  Created by zhaoxin on 2022/6/12.
//
import SwiftUI
struct ContentView: View {
    @State var title = ""
    @State var showTextView = false
    
    var body: some View {
        HStack {
            TextField("Title", text: $title)
        
            Button("Show Text View") {
                showTextView = true
            }
            .sheet(isPresented: $showTextView) {
                TextView(title: $title)
            }
        }
        .padding()
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}//
//  ContentView.swift
//  ViewControllerRepresentable Test
//
//  Created by zhaoxin on 2022/6/12.
//
import SwiftUI
struct ContentView: View {
    @State var title = ""
    @State var showTextView = false
    
    var body: some View {
        HStack {
            TextField("Title", text: $title)
        
            Button("Show Text View") {
                showTextView = true
            }
            .sheet(isPresented: $showTextView) {
                TextView(title: $title)
            }
        }
        .padding()
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
App ran like this and the close button worked.

Update Variables of NSViewController
You may aware that there was a func
func updateNSViewController(_ nsViewController: TextViewController, context: Context) {
    nsViewController.label.stringValue = title
}
We couldn't call nsViewController.label.stringValue = title in makeNSViewController, as in the make function the View Controller was created, but the xib was not loaded. We can think this update as viewDidLoad function in View Controller.