如何为自定义文本字段中的文本行添加限制?

How to add a limit to the lines of text in a customized text field?

我有一个自定义的文本字段,可以让我写多行文本。但是,我想知道是否有办法限制此文本字段允许您写入的行数。设置框架似乎不起作用,因为一旦超过框架的限制,您就会继续向下滚动新行。像 TikTok 或 Instagram 的 edit bio forms 之类的东西,在一定数量后 returns,你不能再进一步了。

这是我目前的情况:

struct NewSnippetTextEditor : UIViewRepresentable {
    
    @Binding var txt : String
    
    var doppleGray = Color(hue: 1.0, saturation: 0.058, brightness: 0.396)
    
    @StateObject var profileData = ProfileViewModel()
    
    func makeCoordinator() -> NewSnippetTextEditor.NewSnippetCoordinator {
        
        return NewSnippetTextEditor.NewSnippetCoordinator(parent1: self)
    }
     
    func makeUIView(context: UIViewRepresentableContext<NewSnippetTextEditor>) -> UITextView {
        let tview = UITextView()
        tview.isEditable = true
        tview.isUserInteractionEnabled = true
        tview.isScrollEnabled = true
        tview.text = "What's up..."
        tview.textColor = .gray
        tview.font = .systemFont(ofSize: 18)
        tview.keyboardType = .twitter
        
        tview.delegate = context.coordinator
        return tview
    }
    
    func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<NewSnippetTextEditor>) {
        
    }
    
    class NewSnippetCoordinator : NSObject, UITextViewDelegate{
        
        var parent : NewSnippetTextEditor
        
        init(parent1 : NewSnippetTextEditor) {
            parent = parent1
        }
        
        func textViewDidChange(_ textView: UITextView) {
            self.parent.txt = textView.text
        }
        
        func textViewDidBeginEditing(_ textView: UITextView) {
            textView.text = ""
            textView.textColor = .label
            
        }
    }
    
}

然后在我使用的视图中显示它:

NewSnippetTextEditor(txt: $newSnippetData.snippetTxt)
                .cornerRadius(20)
                .padding(EdgeInsets.init(top: 0, leading: 20, bottom: 0, trailing: 40))
                .opacity(newSnippetData.isPosting ? 0.5 : 1)
                .disabled(newSnippetData.isPosting ? true : false)

如果这对你不起作用,我还有另一个版本,你可以更好地调整它。

struct NewSnippetTextView: UIViewRepresentable{
    @Binding var text:String
    @Binding var height:CGFloat
    var placeholderText: String
    @State var editing:Bool = false
    
    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.isEditable = true
        textView.isScrollEnabled = true
        textView.text = placeholderText
        textView.delegate = context.coordinator
        textView.textColor = UIColor.white
        textView.backgroundColor = UIColor.black
        textView.font = UIFont.systemFont(ofSize: 18)
        textView.keyboardType = .twitter
        return textView
    }
    
    func updateUIView(_ textView: UITextView, context: Context) {
        if self.text.isEmpty == true{
            textView.text = self.editing ? "" : self.placeholderText
            textView.textColor = self.editing ? .white : .lightGray
        }
        
        DispatchQueue.main.async {
            self.height = textView.contentSize.height
            textView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        }
    }
    
    func makeCoordinator() -> Coordinator {
        NewSnippetTextView.Coordinator(self)
    }
    
    class Coordinator: NSObject, UITextViewDelegate{
        var parent: NewSnippetTextView
        
        init(_ params: NewSnippetTextView) {
            self.parent = params
        }
        
        func textViewDidBeginEditing(_ textView: UITextView) {
            DispatchQueue.main.async {
               self.parent.editing = true
            }
        }
        
        func textViewDidEndEditing(_ textView: UITextView) {
            DispatchQueue.main.async {
               self.parent.editing = false
            }
        }
        
        func textViewDidChange(_ textView: UITextView) {
            DispatchQueue.main.async {
                self.parent.height = textView.contentSize.height
                self.parent.text = textView.text
            }
        }
        
        
    }
    
}

为了显示我使用的第二个版本:

NewSnippetTextView(text: $newSnippetData.snippetTxt, height: $textViewHeight, placeholderText: "What's up")
                .frame(height: textViewHeight < 160 ? self.textViewHeight : 160)
                .cornerRadius(20)
                .padding(EdgeInsets.init(top: 0, leading: 20, bottom: 0, trailing: 40))
                .opacity(newSnippetData.isPosting ? 0.5 : 1)
                .disabled(newSnippetData.isPosting ? true : false)

如何使用标准的 TextEditor 并在更改时检查其长度: (我承认它只计算字符数,不计算行数,但你也可以通过计算换行符来实现)

    TextEditor(text: $textInput)
        .onChange(of: textInput) { newValue in
            if newValue.count > 30 {
                textInput = String(newValue.dropLast(1))
            }
        }