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

UITextView的caretRect换行后minX与maxX返回无穷大问题求助

解决UITextView换行后caretRect返回无穷大导致崩溃的问题

问题原因

UITextView输入换行后,文本布局可能尚未完成,此时调用caretRect(for:)会返回CGRect.infinite,直接访问其minX就会触发崩溃。

解决方案

  • 防御性判断,跳过无效Rect
    在赋值前先检查Rect是否有效,避免异常值引发崩溃:

    if let cursorPosition = messageTextView.selectedTextRange?.start {
        let caretPositionRect = messageTextView.caretRect(for: cursorPosition)
        guard !caretPositionRect.isInfinite else { return }
        leadingAnchor.constant = caretPositionRect.minX
    }
    
  • 通过LayoutManager获取准确光标位置
    直接利用UITextView负责文本布局的layoutManager类获取光标对应的glyph位置,结果更可靠:

    if let cursorPosition = messageTextView.selectedTextRange?.start {
        let glyphIndex = messageTextView.layoutManager.glyphIndex(for: cursorPosition, in: messageTextView.textContainer)
        var glyphRect = messageTextView.layoutManager.boundingRect(forGlyphRange: NSRange(location: glyphIndex, length: 0), in: messageTextView.textContainer)
        glyphRect = messageTextView.convert(glyphRect, from: messageTextView.layoutManager.textContainer)
        leadingAnchor.constant = glyphRect.minX
    }
    
  • 等待布局完成后再执行代码
    在textViewDidChange中通过DispatchQueue.main.async延迟执行,让UITextView完成文本布局后再获取光标位置:

    func textViewDidChange(_ textView: UITextView) {
        DispatchQueue.main.async {
            if let cursorPosition = textView.selectedTextRange?.start {
                let caretPositionRect = textView.caretRect(for: cursorPosition)
                leadingAnchor.constant = caretPositionRect.minX
            }
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 23:30:06