Hello.
I have created the UIComponent using SwiftUI TextField.
struct SearchBar: View { @Binding private var text: String var body: some View { HStack { TextField("", text: $text, prompt: Text("Search")) .textFieldStyle(.plain) .padding() .foregroundStyle(.white) Button { text = "" } label: { Image(systemName: "xmark") .foregroundStyle(.black) } } .padding(.horizontal, 8) .background(RoundedRectangle(cornerRadius: 8).fill(.gray)) .padding(.horizontal, 8) } init(text: Binding<String>) { _text = text } } struct ParentView: View { @State var text = "" var body: some View { SearchBar(text: $text) } }
A text of type String is binded to the component and the text is cleared when the xmark button on the right is pressed.
However, the Japanese text is not cleared under certain conditions.
-
Type in Hiragana, press xmark without pressing “confirm” on the keyboard → can be cleared.
-
Type Hiragana, press “confirm” on the keyboard, and then press xmark→Cannot be cleared.
-
Convert Japanese text to Kanji characters → can be cleared
Does anyone know of a workaround?
The Xcode I used is 16.0.
I believe this issue has been discussed since around iOS 17. Wrapping a UITextField
with UIViewRepresentable
and using the system's standard clear button might be better from an accessibility perspective.
I've thought about several approaches using SwiftUI. I've uploaded a sample project to a repository, so please check it out if you're interested.
https://github.com/CH3COOH/SampleClearJapaneseText
While it's not my original idea, Solution 4, which removes one character and then replaces the text with an empty string in the next event loop, might be a good approach. Here's the sample code:
struct SearchBar4: View { @Binding private var text: String var body: some View { HStack { TextField("", text: $text, prompt: Text("Search")) .textFieldStyle(.plain) .padding() .foregroundStyle(.white) Button { if !text.isEmpty { let _ = text.removeLast() DispatchQueue.main.asyncAfter(deadline: .now()) { self.text = "" } } } label: { Image(systemName: "xmark") .foregroundStyle(.black) } } .padding(.horizontal, 8) .background(RoundedRectangle(cornerRadius: 8).fill(.gray)) .padding(.horizontal, 8) } init(text: Binding<String>) { _text = text } }
The video below shows this sample code in action.