Изменить символы, введенные в TextEditor в SwiftUI

Я пытаюсь захватить текст, введенный в TextEditor, сохранить его в переменной и обновить то, что отображается в самом TextEditor. Я использую .onChange() для запуска и захвата того, что набирается, сохраняю его в переменной и изменяю текущий отображаемый текст. Но проблема в том, что .onChange() вызывается дважды: во-первых, когда я набираю текст внутри TextEditor; и во-вторых, когда я пытаюсь установить другой символ для самого представления.

struct ChatView: View {
    @State var chatTextInput: String = ""
    @State var oldChatValue: String = ""
    @State var newChatValue: String = ""
    
    var body: some View {
        VStack {
            TextEditor(text: $chatTextInput)
                .onChange(of: chatTextInput) { newValue in
                    oldChatValue += "a"
                    newChatValue += newValue.last.map{String($0)}!
                    chatTextInput = oldChatValue
                    
                }
        }
    }
}

Например, если я наберу qwerty, newChatValue будет напечатан как Каваиратая, а chatTextInput получит ааааааааааааааа.

Любые подсказки о том, как предотвратить запуск .onChange во второй раз, когда я устанавливаю новый символ для текста TextEditor?

Большое спасибо!

Возможно, вам лучше объяснить, что именно вы хотите сделать... Вы пытаетесь вставить «а» между каждым введенным символом?

DonMag 10.05.2022 22:29

Или... вы хотите, чтобы "а" показывалось независимо от того, что набрано? Так, например, когда вы вводите «qwerty», вы хотите, чтобы текстовый редактор отображал «aaaaaa», а newChatValue должен содержать «qwerty»?

DonMag 10.05.2022 22:49

@DonMag Да, извините, если я недостаточно ясно выразился. То, что я пытаюсь, это именно то, что вы сказали. Я хочу, чтобы «а» заменило все, что пользователь вводит в TextEditor. И newChatValue должен хранить то, что было напечатано.

Boga 11.05.2022 02:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
30
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша проблема просто в том, что .onChange(of:) не отвечает на TextEditor, а отвечает на переменную, в данном случае chatTextInput. Поскольку chatTextInput привязан к TextEditor, когда вы вводите букву, chatTextInput обновляется и запускается .onChange(of:). Однако, как часть .onChange(of:) выполнения, вы изменяете chatTextInput, который вызывает .onChange(of:) again. You would have an infinite loop, except that .onChange(of:)` на этом заканчивается. Если кто-то может объяснить это, я хотел бы услышать это.

Однако исправление состоит в том, чтобы просто поставить флаг в .onChange(of:), чтобы устанавливать переменные только через раз, например:

struct ChatView: View {
    @State var chatTextInput: String = ""
    @State var oldChatValue: String = ""
    @State var newChatValue: String = ""
    
    @State var textEntryFlag = true
    
    var body: some View {
        VStack {
            TextEditor(text: $chatTextInput)
                .onChange(of: chatTextInput) { newValue in
                    if textEntryFlag {
                        oldChatValue += "a"
                        newChatValue += newValue.last.map{String($0)}!
                        chatTextInput = oldChatValue
                    }
                    textEntryFlag.toggle()
                }
        }
    }
}

Спасибо, это было очень просто и помогло!! Знаете ли вы, есть ли какой-либо другой способ решить эту проблему без использования .onChange(), который действует как ответчик непосредственно в TextEditor?

Boga 11.05.2022 02:37

Для TextEditor больше ничего нет. Для TextField у вас есть .onSubmit(of:), но в настоящее время его не существует для TextEditor.

Yrb 11.05.2022 03:50

Это я и подозревал. В любом случае, еще раз спасибо за вашу помощь!

Boga 11.05.2022 04:44

Другие вопросы по теме