macOS端SwiftUI:如何移除TextEditor间的文本选中状态
解决SwiftUI中多个TextEditor切换时选中状态残留的问题
这个问题的本质是SwiftUI的TextEditor底层基于UIKit的UITextView,系统默认会在UITextView失去焦点后保留选中文本的灰色高亮状态,在多编辑器场景下会出现同时显示多个选中区域的情况。下面提供两种可行的解决方案:
方案一:利用FocusState结合文本刷新(快速实现)
通过@FocusState跟踪当前活跃的编辑器,当某个编辑器失去焦点时,临时修改其绑定的文本内容触发视图刷新,从而清除选中状态:
import SwiftUI struct ContentView: View { @State private var text1 = "Acing cipsusto dictumst ut nisim mincidunt bibendum nostra; tisi niscilit mauris integer. Praesent dolendrem sit tionsequi blandit, iliquamcon quamconsequi aliquam. Doloboreet niat diam facillum torquent, etiam potenti ationullaoret. Euisi ea adignit, modit iliquiscipis, sapien sectem, in quatums vitae sustrud consequipis. Henim faciduisi penatibus, modionsed velisim, consenisim do, lamconullaor sed adiat odionsequip lacinia." @State private var text2 = "Ipsustrud wis nostrud ullan. Dolorem nis tue facincil. Enis lor endre consenibh habitant enissim velestionse quatet nullut; niat ver facilisse acidunt sum hendipisim. Fames diamcom conulluptat facidunt landrem." @FocusState private var focusedField: Field? enum Field { case editor1, editor2 } var body: some View { VStack { TextEditor(text: $text1) .focused($focusedField, equals: .editor1) .onChange(of: focusedField) { newValue in guard newValue != .editor1 else { return } // 临时修改文本触发刷新,清除选中状态 text1 += " " text1.removeLast() } TextEditor(text: $text2) .focused($focusedField, equals: .editor2) .onChange(of: focusedField) { newValue in guard newValue != .editor2 else { return } text2 += " " text2.removeLast() } } } }
优缺点:实现成本低,但修改文本时会有轻微的视觉闪烁,适合快速验证或对体验要求不极致的场景。
方案二:自定义UITextView包装器(无闪烁,更可靠)
通过UIViewRepresentable封装原生UITextView,监听编辑器失去焦点的事件,主动取消文本选中状态:
import SwiftUI import UIKit struct CustomTextEditor: UIViewRepresentable { @Binding var text: String func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.delegate = context.coordinator textView.font = .systemFont(ofSize: 16) // 匹配SwiftUI默认字体 return textView } func updateUIView(_ uiView: UITextView, context: Context) { if uiView.text != text { uiView.text = text } } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, UITextViewDelegate { let parent: CustomTextEditor init(_ parent: CustomTextEditor) { self.parent = parent } func textViewDidChange(_ textView: UITextView) { parent.text = textView.text } func textViewDidEndEditing(_ textView: UITextView) { // 失去焦点时主动取消选中状态 textView.selectedTextRange = nil } } } // 使用示例 struct ContentView: View { @State private var text1 = "Acing cipsusto dictumst ut nisim mincidunt bibendum nostra; tisi niscilit mauris integer. Praesent dolendrem sit tionsequi blandit, iliquamcon quamconsequi aliquam. Doloboreet niat diam facillum torquent, etiam potenti ationullaoret. Euisi ea adignit, modit iliquiscipis, sapien sectem, in quatums vitae sustrud consequipis. Henim faciduisi penatibus, modionsed velisim, consenisim do, lamconullaor sed adiat odionsequip lacinia." @State private var text2 = "Ipsustrud wis nostrud ullan. Dolorem nis tue facincil. Enis lor endre consenibh habitant enissim velestionse quatet nullut; niat ver facilisse acidunt sum hendipisim. Fames diamcom conulluptat facidunt landrem." var body: some View { VStack { CustomTextEditor(text: $text1) CustomTextEditor(text: $text2) } } }
优缺点:完全控制原生组件行为,无视觉闪烁,体验更流畅,但需要自定义组件,代码量稍多。
内容的提问来源于stack exchange,提问作者iphaaw
相关产品推荐
相关产品推荐

