How to make TextView in SwiftUI for macOS

Issue #587

Use xib

Create a xib called ScrollableTextView, and drag just Scrollable text view as top object

Screenshot 2020-01-29 at 06 49 55

Connect just the textView property

1
2
3
4
5
import AppKit

class ScrollableTextView: NSScrollView {
@IBOutlet var textView: NSTextView!
}

Conform to NSViewRepresentable

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 SwiftUI

struct 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

© 2020 onmyway133 All Rights Reserved.
Theme by hiero