swift - 如何在 SwiftUI for MacOS 中创建多行文本字段?

标签 swift macos swiftui

我正在使用 Swift 编写我的第一个 MacOS 应用程序。我需要创建一个允许多个段落的简单可编辑文本框。在 HTML 中,这将是一个 textarea

我了解到 iOS 14 将包含 TextEditor,但那不是现在,我不知道它是否会出现在 MacOS 中。

我见过的许多解决方案都假定 iOS 和 UIKit。

如何使用 SwiftUI 和 MacOS 执行此操作?

更新

有人建议问题与此问题类似:How do I create a multiline TextField in SwiftUI?

我已经看过那个问题了,但是:

  • 链接的问题专门针对 iOS,但我的问题是针对 MacOS
  • 据我所知,这些答案专门针对使用 UIKit 的 iOS。如果有人愿意解释这如何回答我的 MacOS 问题,我会非常感兴趣......

最佳答案

这是一些像 iOS14 TextEditor 这样的组件的初始演示。

使用 Xcode 11.7/macOS 10.15.6 准备和测试的演示

demo

struct TestTextArea: View {
    @State private var text = "Placeholder: Enter some text"

    var body: some View {
        VStack {
            TextArea(text: $text)
                .border(Color.black)
//            Text(text) // uncomment to see mirror of enterred text
        }.padding()
    }
}

struct TextArea: NSViewRepresentable {
    @Binding var text: String

    func makeNSView(context: Context) -> NSScrollView {
        context.coordinator.createTextViewStack()
    }

    func updateNSView(_ nsView: NSScrollView, context: Context) {
        if let textArea = nsView.documentView as? NSTextView, textArea.string != self.text {
            textArea.string = self.text
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(text: $text)
    }

    class Coordinator: NSObject, NSTextViewDelegate {
        var text: Binding<String>

        init(text: Binding<String>) {
            self.text = text
        }

        func textView(_ textView: NSTextView, shouldChangeTextIn range: NSRange, replacementString text: String?) -> Bool {
            defer {
                self.text.wrappedValue = (textView.string as NSString).replacingCharacters(in: range, with: text!)
            }
            return true
        }

        fileprivate lazy var textStorage = NSTextStorage()
        fileprivate lazy var layoutManager = NSLayoutManager()
        fileprivate lazy var textContainer = NSTextContainer()
        fileprivate lazy var textView: NSTextView = NSTextView(frame: CGRect(), textContainer: textContainer)
        fileprivate lazy var scrollview = NSScrollView()

        func createTextViewStack() -> NSScrollView {
            let contentSize = scrollview.contentSize

            textContainer.containerSize = CGSize(width: contentSize.width, height: CGFloat.greatestFiniteMagnitude)
            textContainer.widthTracksTextView = true

            textView.minSize = CGSize(width: 0, height: 0)
            textView.maxSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
            textView.isVerticallyResizable = true
            textView.frame = CGRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height)
            textView.autoresizingMask = [.width]
            textView.delegate = self

            scrollview.borderType = .noBorder
            scrollview.hasVerticalScroller = true
            scrollview.documentView = textView

            textStorage.addLayoutManager(layoutManager)
            layoutManager.addTextContainer(textContainer)

            return scrollview
        }
    }
}

关于swift - 如何在 SwiftUI for MacOS 中创建多行文本字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63760116/

相关文章:

r - 在Mac(iMac OSX)终端中远程运行脚本(r脚本)到其他计算机

ios - SwiftUI:如何关闭模式表,然后一起执行导航链接

swift - 需要帮助使用 foreach 在 swift ui 中增加数字

ios - 如何安全高效地轮询 API?

ios - 使用滑动手势更改 View

ios - 水平滚动而不是垂直滚动时更改 ScrollView 页面

macos - 如何在 Mac OS X 中禁用键盘快捷键?

mysql - 无法启动 MySQL

swift - 从 View 之外的函数访问@StateObject

xcode - 从 Xcode 的控制台打印 (po) Swift 匿名闭包参数的值