SwiftUI — Запретить пользователям добавлять новую строку (n) в TextEditor

#ios #swiftui #text-editor

#iOS #swiftui #текстовый редактор

Вопрос:

У меня есть TextEditor, в котором я не разрешаю пользователям добавлять в него новую строку ( n). То есть, когда пользователь вводит, я отключаю клавиатуру. Я использовал следующий код, чтобы отменить привязку клавиш и запретить пользователям добавлять новую строку.

Клавиатура отключается при вводе, но это не мешает пользователям добавлять новую строку. При вводе.

 extension View {
  func  dismissKeyboard(){
        let keyWindow = UIApplication.shared.connectedScenes
                .filter({$0.activationState == .foregroundActive})
                .map({$0 as? UIWindowScene})
                .compactMap({$0})
                .first?.windows
                .filter({$0.isKeyWindow}).first
        keyWindow?.endEditing(true)
    }
}


struct Editor: View {
    
    @Binding var text: String
        
    var onEditingEnded: () -> ()
    
    var body: some View {
        ZStack(alignment: .leading) {         
            TextEditor(text: $text)
                .onChange(of: text) { value in
                    if value.last == "n" {
                        self.dismissKeyboard()
                        self.onEditingEnded()
                    }
                }
        }
        .padding(8)
        .font(.body)
    }
}
  

Как запретить пользователям добавлять новую строку?

Комментарии:

1. Почему бы вам просто не использовать TextField?

2. @Asperi Разве TextFeild не является однострочным? Я хочу, чтобы пользователи вводили столько текста, сколько пожелают. И все слова должны быть видны. Это функция такая же, как у TextEditor / UITextView в приложении напоминания iOS.

Ответ №1:

Вы могли бы использовать a UITextView , который имеет shouldChangeTextIn range функцию делегирования…

Или, хотя я бы не назвал это идеальным, это может сработать для вас:

 TextEditor(text: $text)
            
    .onChange(of: text) { value in
        if value.last == "n" {
            text = String(value.dropLast())
            self.dismissKeyboard()
            self.onEditingEnded()
        }
    }
  

Обратите внимание, что вы проверяете только последний символ в строке, поэтому это не приведет к добавлению пользователем новой строки в середине существующего текста.

Итак, вы могли бы вместо этого попробовать:

 TextEditor(text: $text)

    .onChange(of: text) { value in
        if value.contains("n") {
            text = value.replacingOccurrences(of: "n", with: "")
            self.dismissKeyboard()
            self.onEditingEnded()
        }
    }
  

Комментарии:

1. Почему это не идеально? Есть ли какие-либо проблемы с заменой символов новой строки, как у вас?

2. @mahan — я должен уточнить… Выполнение этого способа изменяет текст после того, как он уже был введен, в отличие от shouldChangeTextIn range метода UITextView , который перехватывает ввод и позволяет вам решить, что делать заранее. Конечно, я потратил, вероятно, менее 8 часов на просмотр SwiftUI, поэтому многое из этого кажется мне странным, так что в этом подходе действительно нет ничего плохого..

3. Спасибо. Ваше решение работает. Однако, как вы уже упоминали, вместо этого я использовал UITextView, поскольку вы можете установить его в качестве первого респондента.

Ответ №2:

Аналогично ответу DonMag, вы также можете использовать Binding() вместо .onChange() , чтобы избежать последующего изменения значения и действовать до его установки:

 TextEditor(text: Binding(
    get: {
        return text
    },
    set: { value in
        var newValue = value
        if value.contains("n") {
            newValue = value.replacingOccurrences(of: "n", with: "")
            self.dismissKeyboard()
            self.onEditingEnded()
        }
        text = newValue
    }
))