【问题标题】:swift cursor position with emojis带有表情符号的快速光标位置
【发布时间】:2019-05-04 07:36:04
【问题描述】:

我用来获取 UITextfield 中光标位置的标准方法似乎不适用于某些表情符号。以下代码在插入两个字符(首先是表情符号,然后是字母字符)后查询文本字段以获取光标位置。当表情符号插入到 textField 中时,函数为光标位置返回值 2,而不是预期的结果 1。关于我做错了什么或如何纠正这个问题的任何想法。谢谢

这是来自 xcode 游乐场的代码:

class MyViewController : UIViewController {

override func loadView() {
    //setup view
    let view = UIView()
    view.backgroundColor = .white
    let textField = UITextField()
    textField.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
    textField.textColor = .black
    view.addSubview(textField)
    self.view = view

    //check cursor position
    var str = "????"
    textField.insertText(str)
    print("cursor position after '\(str)' insertion is \(getCursorPosition(textField))")

    textField.text = ""
    str = "A"
    textField.insertText(str)
     print("cursor position after '\(str)' insertion is \(getCursorPosition(textField))")
}

func getCursorPosition(_ textField: UITextField) -> Int {
    if let selectedRange = textField.selectedTextRange {
        let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.end)
        return cursorPosition
    }
    return -1
}

}

代码返回以下输出:

cursor position after '????' insertion is 2
cursor position after 'A' insertion is 1

我正在尝试使用光标位置将文本字符串分成两部分——出现在光标之前的文本和出现在光标之后的文本。为此,我使用光标位置作为我使用 map 函数创建的字符数组的索引,如下所示。光标位置导致带有表情符号的数组索引不正确

    var textBeforeCursor = String()
    var textAfterCursor = String()
    let array = textField.text!.map { String($0) }
    let cursorPosition = getCursorPosition(textField)
    for index in 0..<cursorPosition {
        textBeforeCursor += array[index]
    }

【问题讨论】:

  • 一些表情符号字母由两个 Unicode 字符组成。有些由三个 unicode 字符组成。也有许多由四个 unicode 字符组成的表情符号。
  • 是的,但是当我尝试使用光标位置将文本分成两部分时遇到了问题。我将编辑问题以使事情更清楚。

标签: swift string emoji cursor-position


【解决方案1】:

您的问题是UITextField selectedTextRangeoffset 返回的NSRange 值需要正确转换为Swift String.Index

func getCursorPosition(_ textField: UITextField) -> String.Index? {
    if let selectedRange = textField.selectedTextRange {
        let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.end)
        let positionRange = NSRange(location: 0, length: cursorPosition)
        let stringOffset = Range(positionRange, in: textField.text!)!

        return stringOffset.upperBound
    }

    return nil
}

一旦你有了String.Index,你就可以拆分字符串了。

if let index = getCursorPosition(textField) {
    let textBeforeCursor = textField.text![..<index]
    let textAfterCursor = textField.text![index...]
}

【讨论】:

  • 你能解释一下为什么这行得通吗?我试图调试每一行,但不知何故无法理解为什么positionRange 起了主要作用。
  • @Dennis 简而言之,UITextFieldselectedTextRange 属性基于字符串的 UTF-16 编码。这需要转换为基于字符数的 Swift String.Index
  • 啊,有道理,我也是这么想的……只是想确认一下。感谢您的回复:)
  • 我使用了上面的代码,输入:abc&lt;emoji&gt;&lt;emoji&gt;&lt;emoji&gt;|cd [cursor position is before “cd”]预期结果:光标前的文本:abc&lt;emoji&gt;&lt;emoji&gt;&lt;emoji&gt;实际结果:光标前的文本:abc&lt;junk character&gt;&lt;emoji&gt;&lt;emoji&gt;对此有什么想法吗?
  • 我使用您的代码从“textBeforeCursor”中删除字符,但在将单个字符删除到字符串末尾后,光标似乎正在设置。你有什么提示我如何保持光标的位置?
猜你喜欢
  • 2018-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-18
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多