Swift为什么退格键的strcmp返回-92?

时间:2018-07-29 05:39:24

标签: swift strcmp uitextfielddelegate backspace

我试图检测UITextfieldDelegate内部的退格键。 并找到了这个答案。 https://stackoverflow.com/a/49294870/911528

而且它可以正常工作。

但是我不知道该函数内部发生了什么。

let  char = string.cString(using: String.Encoding.utf8)!
let isBackSpace = strcmp(char, "\\b")

if isBackSpace == -92 {
    print("Backspace was pressed")
    return false
}
  1. 我不知道为什么退格cString的结果为0。 我可以在XCode上调试。请检查屏幕截图。

enter image description here

  1. 我不知道为什么退格的strcmp大约为0(据我在XCode调试器上获得的值)和“ \ b”字符​​返回-92

enter image description here

我知道Backspace的ascii代码是int类型的“ 8”,因此我认为上面的函数将类似于下面的代码。

// I thought this char would be "\b" of type char or 08 of type int
// but XCode give the value 0... I don't know why
let char = string.cString(using: String.Encoding.utf8)!

// as far as I know, strcmp returns positive value for equal values.
let isBackSpace = strcmp(char, "\\b")

// so I thought this would be
if isBackSpace > 0 {
    print("Backspace was pressed")
    return false // or true
}

有人可以逐步解释此代码吗? 谢谢。

ref:

https://linux.die.net/man/3/strcmp

https://theasciicode.com.ar/ascii-control-characters/backspace-ascii-code-8.html


现在我可以理解为什么人们使用该代码了, 并且上面的代码不正确。

尝试通过引用@Cristik的答案来正确编辑。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // backspace checking
        if string == "" {
            return true // or false
        }

1 个答案:

答案 0 :(得分:3)

让我们分析一下代码和流经该代码的数据:

  1. string是一个空字符串,因为删除字符时,文本字段会尝试用“ nothing”(空字符串)替换它
  2. 由于#1,char仅在内存\0中保留字符串终止符[0]
  3. “ \\ b”转换为\b内存中的[92, 98]字符串
  4. 由于#2和#3,strcmp返回0-92 => -92。

不知道为什么人们只用检查string参数是否为空时为什么使用此“算法”。我认为他们首先尝试使用\b转义序列,这似乎不是一个有效的转义序列,因此他们添加了一个额外的\字符,该字符已编译,但导致了不正确的转义序列,因为\\是反斜杠字符的转义序列,导致b部分用纯字母表示。

似乎委托方法没有报告退格,而是要求委托方法对字符串进行操作。检测实际的按键操作可能需要一些UIEvent / RunLoop钩子。

请注意,传递给textField(_,shouldChangeCharactersIn:,replacementString:)的空字符串并不总是意味着退格键已被按下,剪切操作也可能导致将空字符串发送给委托。您可以尝试检查范围,并假设按下了1个退格键,但是用户也可以剪切一个字符...