You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SwiftUI中从UITextViewRepresentable的textViewDidChangeSelection代理方法获取选中范围并传递至ContentView

Pass UITextView Selected Range to SwiftUI ContentView

Got it, let's solve this problem of passing the UITextView's selected range from the textViewDidChangeSelection delegate method up to your SwiftUI ContentView. Here's how you can do it step by step:

Step 1: Add a Binding for Selected Range in UITextViewRepresentable

First, we'll add a @Binding property to hold the selected range, which will let us sync the value between UIKit and SwiftUI. Also, fix the UITextView initialization (don't declare it as a stored property on the struct—create it inside makeUIView to avoid reuse issues).

Step 2: Update the Coordinator to Sync Selected Range

Pass the new selected range binding to the Coordinator, then update it whenever the selection changes in textViewDidChangeSelection.

Step 3: Use the Selected Range in ContentView

Add a @State variable to track the selected range in your ContentView, and pass it to the UITextViewRepresentable.

Complete Modified Code

struct ContentView: View {
    @State private var text = ""
    @State private var selectedRange = NSRange(location: 0, length: 0) // Track selected range here
    
    var body: some View {
        VStack {
            UITextViewRepresentable(text: $text, selectedRange: $selectedRange)
            
            // Show the selected range in SwiftUI
            Text("Selected Range: Location \(selectedRange.location), Length \(selectedRange.length)")
                .padding()
        }
    }
}

struct UITextViewRepresentable: UIViewRepresentable {
    @Binding var text: String
    @Binding var selectedRange: NSRange // New binding for selected range
    
    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView() // Create textView here instead of stored property
        textView.delegate = context.coordinator
        return textView
    }
    
    func updateUIView(_ uiView: UITextView, context: Context) {
        // Only update text if it's different to avoid overwriting selection
        if uiView.text != text {
            uiView.text = text
        }
        // Optional: Sync selection from SwiftUI to UIKit if needed
        // if uiView.selectedRange != selectedRange {
        //     uiView.selectedRange = selectedRange
        // }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(text: $text, selectedRange: $selectedRange) // Pass selectedRange binding
    }
    
    class Coordinator: NSObject, UITextViewDelegate {
        @Binding var text: String
        @Binding var selectedRange: NSRange // Hold the binding
        
        init(text: Binding<String>, selectedRange: Binding<NSRange>) {
            self._text = text
            self._selectedRange = selectedRange
        }
        
        func textViewDidChange(_ textView: UITextView) {
            text = textView.text ?? ""
        }
        
        func textViewDidChangeSelection(_ textView: UITextView) {
            // Update the binding with the new selected range
            selectedRange = textView.selectedRange
            print("Selected Range: \(textView.selectedRange)")
        }
    }
}

Key Notes:

  • We added a check in updateUIView to only update the text if it's different—this prevents overwriting the user's selection when SwiftUI updates the view.
  • The selectedRange binding flows both ways: if you update it in SwiftUI, you can sync it back to the UITextView (uncomment the optional code in updateUIView if you need that).
  • Now your ContentView has access to the current selected range, which you can use for any UI updates or logic.

内容的提问来源于stack exchange,提问作者Dev Rana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 13:22:27