Swift why strcmp of backspace returns -92?
Asked Answered
I

1

10

I was tried to detecting backspace inside of UITextfieldDelegate. And found this answer. https://mcmap.net/q/162091/-detect-backspace-event-in-uitextfield

And It working correctly.

But I don't know what's going on inside of this function.

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

if isBackSpace == -92 {
    print("Backspace was pressed")
    return false
}
  1. I don't know why the result of cString of backspace is 0. I can debug on XCode. Please check the screenshot.

enter image description here

  1. I don't know why the strcmp about 0 for backspace(as far as I got this value on XCode debugger) and "\b" character returns -92

enter image description here

I knew the ascii code of backspace is "8" of type int so I thought above function would be like this code below.

// 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
}

Does anyone who can explain about this code step-by-step? Thank you.

ref :

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

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


Now I can understand why people use that code, and the code above is not correct.

Try to edit correctly by reffering to @Cristik's answer.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // backspace checking
        if string == "" {
            return true // or false
        }
Intercessory answered 29/7, 2018 at 5:39 Comment(0)
S
11

Let's analyze a little bit the code and the data that flows through that code:

  1. string is an empty string, as when you delete a character, the textfield tries to replace it by "nothing" (an empty string)
  2. due to #1, char holds only the string terminator, which is \0, in memory: [0]
  3. "\\b" translates to the \b string, in memory: [92, 98]
  4. due to #2 and #3, strcmp returns 0 - 92 => -92.

Not sure why people use this "algorithm", when they could simply check for the emptiness of the string parameter. I assume they firstly tried to use the \b escape sequence, which doesn't seem to be a valid one, so they added an extra \ character, which compiled, but resulted in an incorrect escape sequence, as \\ is the escaping sequence for the backslash character, resulting in the b part being represented as the plain letter.

Seems that backspace is not reported by the delegate method, instead the delegate method is asked to operate on strings. Detecting the actual key press might need some UIEvent/RunLoop hooks.

Note that an empty string passed to textField(_,shouldChangeCharactersIn:,replacementString:) doesn't always mean that backspace was presset, a cut operation might result too in an empty string being sent to the delegate. You could try and check the range and assume that for a range of 1 backspace was pressed, however the user can also cut one character...

Starkey answered 29/7, 2018 at 6:27 Comment(4)
Perfect answer! thanks a lot! I got what you are saying 100%. So I'll update my code by reffering to your answer.Intercessory
@Intercessory a couple of notes: adding parts of the answer to the question is not a recommended SO practice, the question and answers sections should be used for their intended purposes. Secondly, please check the last paragraph I added today, an empty string doesn't necessarily mean that backspace was pressed.Starkey
Excellent answer... I have been using this for almost 2 years and now it is clear that it is a totally flawed 'algorithm' that works by chance.... You could use the "\\x" and it will work, because as @Starkey points, the strcmp is only evaluating the first element of the 'escaped sequence' against an empty inputPedicle
I can inform that using: strcmp(char, "x") // x = ASCII 120 and then: if isBackSpace == -120 And it will work...Pedicle

© 2022 - 2024 — McMap. All rights reserved.