How to make attributed string Text in SwiftUI for macOS

Issue #730

Use NSTextField with maximumNumberOfLines

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
import AppKit
import SwiftUI

struct AttributedText: NSViewRepresentable {

let attributedString: NSAttributedString

init(_ attributedString: NSAttributedString) {
self.attributedString = attributedString
}

func makeNSView(context: Context) -> NSTextField {
let textField = NSTextField()

textField.lineBreakMode = .byClipping
textField.maximumNumberOfLines = 0
textField.isBordered = false

return textField
}

func updateNSView(_ nsView: NSTextField, context: Context) {
nsView.attributedStringValue = attributedString
}
}

TextField has problem with wrapping, we can use TextView

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
struct AttributedTextView: NSViewRepresentable {
typealias NSViewType = NSScrollView

let attributedText: NSAttributedString?
let isSelectable: Bool
var insetSize: CGSize = .zero

func makeNSView(context: Context) -> NSViewType {
let scrollView = NSTextView.scrollableTextView()

let textView = scrollView.documentView as! NSTextView
textView.drawsBackground = false
textView.textColor = .controlTextColor
textView.textContainerInset = insetSize

return scrollView
}

func updateNSView(_ nsView: NSViewType, context: Context) {
let textView = (nsView.documentView as! NSTextView)
textView.isSelectable = isSelectable

if let attributedText = attributedText,
attributedText != textView.attributedString() {
textView.textStorage?.setAttributedString(attributedText)
}

if let lineLimit = context.environment.lineLimit {
textView.textContainer?.maximumNumberOfLines = lineLimit
}
}
}

Updated at 2020-12-31 05:51:42

Comments