Issue #587
Use NSTextVIew From https://github.com/twostraws/ControlRoom/blob/main/ControlRoom/NSViewWrappers/TextView.swift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 import SwiftUIstruct TextView : NSViewRepresentable { @Binding private var text: String private let isEditable: Bool init (text: Binding <String >, isEditable: Bool = true ) { _text = text self .isEditable = isEditable } init (text: String ) { self .init (text: Binding <String >.constant(text), isEditable: false ) } func makeNSView (context: Context) -> NSScrollView { let text = NSTextView () text.backgroundColor = isEditable ? .textBackgroundColor : .clear text.delegate = context.coordinator text.isRichText = false text.font = NSFont .monospacedSystemFont(ofSize: NSFont .systemFontSize, weight: .regular) text.autoresizingMask = [.width] text.translatesAutoresizingMaskIntoConstraints = true text.isVerticallyResizable = true text.isHorizontallyResizable = false text.isEditable = isEditable let scroll = NSScrollView () scroll.hasVerticalScroller = true scroll.documentView = text scroll.drawsBackground = false return scroll } func updateNSView (_ view: NSScrollView, context: Context) { let text = view.documentView as ? NSTextView text?.string = self .text guard context.coordinator.selectedRanges.count > 0 else { return } text?.selectedRanges = context.coordinator.selectedRanges } func makeCoordinator () -> Coordinator { Coordinator (self ) } class Coordinator : NSObject , NSTextViewDelegate { var parent: TextView var selectedRanges = [NSValue ]() init (_ parent: TextView ) { self .parent = parent } func textDidChange (_ notification: Notification) { guard let textView = notification.object as ? NSTextView else { return } parent.text = textView.string selectedRanges = textView.selectedRanges } } }
Use xib Create a xib called ScrollableTextView
, and drag just Scrollable text view
as top object
Connect just the textView
property
1 2 3 4 5 import AppKitclass ScrollableTextView : NSScrollView { @IBOutlet var textView: NSTextView! }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import SwiftUIstruct TextView : NSViewRepresentable { @Binding var text: String func makeCoordinator () -> Coordinator { Coordinator (self ) } func makeNSView (context: Context) -> ScrollableTextView { var views: NSArray? Bundle .main.loadNibNamed("ScrollableTextView" , owner: nil , topLevelObjects: &views) let scrollableTextView = views!.compactMap({ $0 as ? ScrollableTextView }).first! scrollableTextView.textView.delegate = context.coordinator return scrollableTextView } func updateNSView (_ nsView: ScrollableTextView, context: Context) { guard nsView.textView.string != text else { return } nsView.textView.string = text } class Coordinator : NSObject , NSTextViewDelegate { let parent: TextView init (_ textView: TextView ) { self .parent = textView } func textDidChange (_ notification: Notification) { guard let textView = notification.object as ? NSTextView else { return } self .parent.text = textView.string } } }
There seems to be a bug that if we have open and close curly braces, any character typed into NSTextView will move the cursor to the end. This is easily fixed with a check in updateNSView
Updated at 2021-02-24 21:50:17