ios 当换行符在最后一行之前+该行最后一个字符之后开始时,光标始终跳转到UIViewRepresentable TextView的末尾

jvlzgdj9  于 2023-04-22  发布在  iOS
关注(0)|答案(4)|浏览(253)

我依赖于TextView使用UIViewRepresentable在这里创建https://www.appcoda.com/swiftui-textview-uiviewrepresentable/

struct TextView: UIViewRepresentable {
    
    @Binding var text: String
    @Binding var textStyle: UIFont.TextStyle
    
    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        
        textView.delegate = context.coordinator
        textView.font = UIFont.preferredFont(forTextStyle: textStyle)
        textView.autocapitalizationType = .sentences
        textView.isSelectable = true
        textView.isUserInteractionEnabled = true
        
        return textView
    }
    
    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.text = text
        uiView.font = UIFont.preferredFont(forTextStyle: textStyle)
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator($text)
    }
    
    class Coordinator: NSObject, UITextViewDelegate {
        var text: Binding<String>

        init(_ text: Binding<String>) {
            self.text = text
        }
        
        func textViewDidChange(_ textView: UITextView) {
            self.text.wrappedValue = textView.text
        }
    }
}

struct ContentView: View {
    
    @State private var message = ""
    @State private var textStyle = UIFont.TextStyle.body
    
    var body: some View {
        ZStack(alignment: .topTrailing) {
            TextView(text: $message, textStyle: $textStyle)
                .padding(.horizontal)
            
            Button(action: {
                self.textStyle = (self.textStyle == .body) ? .title1 : .body
            }) {
                Image(systemName: "textformat")
                    .imageScale(.large)
                    .frame(width: 40, height: 40)
                    .foregroundColor(.white)
                    .background(Color.purple)
                    .clipShape(Circle())
                
            }
            .padding()    
        }
    }
}

我遇到的问题是,每当我在最后一行 * 之前+ 2)最后一个字符 * 之后开始一个换行符时,光标总是跳到文本中最后一个字符的后面。

更新

Leo的回应在技术上解决了这个问题,但它似乎并不完美,因为存在不希望的滚动行为,即尽管插入符号位置现在是正确的,但不会停止自动滚动到底部。请参阅下文:

rqdpfwrv

rqdpfwrv1#

在updateUIView方法中设置text属性后,可以保存插入符号位置(selectedRange)并设置文本视图的选定范围:

func updateUIView(_ uiView: UITextView, context: Context) {
    let selectedRange = uiView.selectedRange
    uiView.text = text
    uiView.font = .preferredFont(forTextStyle: textStyle)
    uiView.selectedRange = selectedRange
}
gupuwyp2

gupuwyp22#

除了Leo answer之外,我注意到如果你用一个“新行”字符开始编辑,你的textView也可能跳到末尾。

func updateUIView(_ uiView: UITextView, context: Context) {
   //previous code
   uiView.scrollRangeToVisible(selectedRange)
}
waxmsbnn

waxmsbnn3#

这是因为每次符号更改时都要设置字体。如果不需要,请尽量不要太频繁地设置样式

wlp8pajw

wlp8pajw4#

对于像我这样的人来说,这里是为了光标跳跃,不关心字体是否是绑定的(只需在makeUIView中设置字体):
就像Leo在他的回答的评论中提到的那样,这是由于在updateUIView()中设置文本引起的。当SwiftUI看到更新时,您希望UITextView更新。
问题是textViewDidChange()会更新你的绑定(它应该这样做),然后SwiftUI会看到更新并调用updateUIView(),所以你最终会得到重复的更新。要解决这个问题,你只需要避免重复的更新。
就像这样:

func updateUIView(_ uiView: UITextView, context: Context) {
    if text != uiView.text {
        uiView.text = text
        //uiView.font = UIFont.preferredFont(forTextStyle: textStyle)
    }
}

相关问题