swift 如何在UITextview中将光标定位在占位符文本的开头

jslywgbw  于 2023-04-19  发布在  Swift
关注(0)|答案(2)|浏览(204)

我花了很多时间试图解决这个简单的问题,但没有管理它。我想在UITextView中使用占位符:“翻译”,当点击UITextView占位符应该留在那里,直到一个字符被输入,但我需要光标被放置在占位符的开头就在“翻译”字,但它留在我的占位符的结尾.我找到几个答案,并试图这样做,但不工作.占位符正确更改为黑色,但第二个命令-〉textView.selectedRange =NSMakeRange(0,0)没有将光标移动到开始处,为什么?

  • 我用以下代码替换了这一行NSMakeRange(我读到的其他建议,但结果相同,不起作用)-〉textView.selectedTextRange = textView.textRange(from:textView.beginningOfDocument,用于:textView.beginningOfDocument)

下面是完整的代码:

class MainViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate {
    

    @IBOutlet weak var definitionField: UITextView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // setting placeholder
        definitionField.textColor = .gray
        definitionField.text = "translation"
        
        definitionField.delegate = self    }
    
    
    func textViewDidBeginEditing(_ textView: UITextView) {
        if (textView.text == "translation") {

            textView.textColor = .black
            textView.selectedRange = NSMakeRange(0, 0)
        }
    }

    func textViewDidEndEditing(_ textView: UITextView) {
        if (textView.text == "") {
           textView.text = "translation"
           textView.textColor = .gray
        }
        textView.resignFirstResponder()
    }
lskq00tm

lskq00tm1#

textViewDidBeginEditingbecomeFirstResponder被调用之后,系统似乎自动设置了selectedTextRange。您可以通过使用自定义UITextView子类并重写来观察这一点:

override var selectedTextRange: UITextRange? {
    didSet {
        print(selectedTextRange)
    }
}

您将看到,由于您的代码,它首先被设置为(0, 0),然后didSet被再次“神奇地”调用,将selectedTextRange设置为(11, 0)
我不确定是哪个方法调用了这个函数,甚至可能没有一个可重写的方法在那之后被调用。
一个简单的解决方案是使用DispatchQueue.main.async来等待将所选文本范围设置到末尾的任何内容,然后 * 更改选择。

// in textViewDidBeginEditing
DispatchQueue.main.async {
    textView.selectedRange = NSMakeRange(0, 0)
}

光标将在结束时出现一小会儿,然后再转到开始。这似乎只是视觉上的。当我试图在光标位于结束时输入文本时,文本被插入到“翻译”之前。
也就是说,这个占位符的实现似乎与人们期望的占位符的工作方式(如UITextField中的占位符)有很大的不同,特别是当textViewDidEndEditing时。
如果你想要类似于UITextField的行为,或者想看看其他方法,请查看this post

7d7tgy0s

7d7tgy0s2#

这里最简单的解决方案是添加一个包含占位符的标签。然后根据文本视图中是否有任何文本来设置其isHidden属性。
Here is a working example,但它使用RxSwift来跟踪文本、颜色和字体的变化。
它的作用:
1.创建一个标签并将其嵌入到文本视图的适当位置。
1.监视文本视图的tintColor并更新标签的textColor。
1.监视文本视图的字体并更新标签的字体。
1.监视文本视图的文本,并根据是否存在任何文本更新标签的isHidden属性。

extension UITextView {
    func withPlaceholder(_ placeholder: String) {
        let label = {
            let result = UILabel(frame: bounds)
            result.text = placeholder
            result.numberOfLines = 0
            result.frame = result.frame.offsetBy(dx: 4, dy: 8)
            return result
        }()

        addSubview(label)

        _ = rx.observe(UIColor.self, "tintColor")
            .take(until: rx.deallocating)
            .bind(to: label.rx.textColor)

        _ = rx.observe(UIFont.self, "font")
            .map { $0 != nil ? $0 : UIFont.systemFont(ofSize: 12) }
            .take(until: rx.deallocating)
            .bind(onNext: { [weak self] font in
                label.font = font
                label.frame.size = label.sizeThatFits(self?.bounds.size ?? CGSize.zero)
            })

        _ = rx.text.orEmpty.map { !$0.isEmpty }
            .take(until: rx.deallocating)
            .bind(to: label.rx.isHidden)
    }
}

相关问题