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

如何在SwiftUI for MacOS中创建多行文本字段?,swift,macos,swiftui,Swift,Macos,Swiftui,我正在使用Swift编写我的第一个MacOS应用程序。我需要创建一个简单的可编辑文本框,允许多个段落。在HTML中,这将是一个textarea 我推测iOS 14将包括文本编辑器,但现在不是这样,我不知道MacOS是否也会有这样的功能 我见过的许多解决方案都采用iOS和UIKit 如何使用SwiftUI和MacOS实现这一点 更新 有人提出这个问题与此类似: 我已经看过这个问题,但是: 相关的问题是专门针对iOS的,但我的问题是针对MacOS的 据我所知,答案是专门针对使用UIKit的iOS的

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

我推测iOS 14将包括
文本编辑器
,但现在不是这样,我不知道MacOS是否也会有这样的功能

我见过的许多解决方案都采用iOS和UIKit

如何使用SwiftUI和MacOS实现这一点

更新

有人提出这个问题与此类似:

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

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

这里是iOS14 TextEditor等组件的初步演示

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

struct TestTextArea:View{
@State private var text=“占位符:输入一些文本”
var body:一些观点{
VStack{
text区域(text:$text)
.边框(颜色.黑色)
//Text(Text)//取消注释以查看输入文本的镜像
}.padding()
}
}
结构文本区域:NSViewRepresentable{
@绑定变量文本:字符串
func makeNSView(上下文:context)->NSScrollView{
context.coordinator.createTextViewStack()文件
}
func updateNSView(\nsView:NSScrollView,context:context){
如果让textArea=nsView.documentView为?NSTextView,则textArea.string!=self.text{
textArea.string=self.text
}
}
func makeCoordinator()->Coordinator{
协调员(文本:$text)
}
类协调器:NSObject、NSTextViewDelegate{
var文本:绑定
init(文本:绑定){
self.text=文本
}
func textView(textView:NSTextView,shouldChangeTextIn范围:NSRange,replacementString text:String?->Bool{
推迟{
self.text.wrappedValue=(textView.string作为NSString)。replacingCharacters(在:范围内,使用:text!)
}
返回真值
}
fileprivate lazy var textStorage=NSTextStorage()
fileprivate 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{
让contentSize=scrollview.contentSize
textContainer.containerSize=CGSize(宽度:contentSize.width,高度:CGFloat.greatestfinitemagnity)
textContainer.widthTracksTextView=true
textView.minSize=CGSize(宽度:0,高度:0)
textView.maxSize=CGSize(宽度:CGFloat.GreatestFiniteMagnite,高度:CGFloat.GreatestFiniteMagnite)
textView.isVerticallyResizable=true
textView.frame=CGRect(x:0,y:0,宽度:contentSize.width,高度:contentSize.height)
textView.autoresizingMask=[.width]
textView.delegate=self
scrollview.borderType=.noBorder
scrollview.hasVerticalScroller=true
scrollview.documentView=textView
textStorage.addLayoutManager(layoutManager)
layoutManager.addTextContainer(textContainer)
返回滚动视图
}
}
}

这是否回答了您的问题@谢谢,我已经看过了。据我所知,它需要UIKit,这是MacOS应用程序无法使用的。这太棒了。你真的是瞎编的吗?我有许可在真实的项目中使用它吗?我在哪里可以了解更多关于你所做的事情?这是一个演示。您可以根据需要使用或修改它。如果你的项目是开源的,如果你想(有人这样做),你可以在相应的源代码模块中添加对这篇文章的引用,但这取决于你。还有一件事:有没有办法在文本区域中添加填充?
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
        }
    }
}