Swift, почему strcmp backspace возвращает -92?

Меня пытались обнаружить 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. Пожалуйста, проверьте скриншот.

введите описание изображения здесь

  1. Я не знаю, почему strcmp около 0 для возврата (насколько я получил это значение в отладчике XCode), а символ "\ b" возвращает -92

введите описание изображения здесь

Я знал, что код ascii backspace равен «8» типа int, поэтому я подумал, что вышеприведенная функция будет похожа на этот код ниже.

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

Кто-нибудь может объяснить этот код шаг за шагом? Спасибо.

ссылка:

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

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


Теперь я могу понять, почему люди используют этот код, а приведенный выше код неверен.

Попробуйте правильно отредактировать, обратившись к ответу @Cristic.

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

person AutumnSky    schedule 29.07.2018    source источник


Ответы (1)


Давайте немного проанализируем код и данные, которые проходят через этот код:

  1. string — это пустая строка, так как при удалении символа текстовое поле пытается заменить его «ничего» (пустая строка)
  2. из-за #1, char содержит только терминатор строки, то есть \0, в памяти: [0]
  3. "\\b" преобразуется в строку \b в памяти: [92, 98]
  4. из-за #2 и #3, strcmp возвращает 0 - 92 => -92.

Не знаю, зачем люди используют этот "алгоритм", когда можно было просто проверить на пустоту параметр string. Я предполагаю, что сначала они попытались использовать escape-последовательность \b, которая кажется недействительной, поэтому они добавили дополнительный символ \, который скомпилировался, но привел к неправильной escape-последовательности, поскольку \\ — это escape-последовательность для символ обратной косой черты, в результате чего часть b представляется как простая буква.

Кажется, что метод делегата не сообщает о возврате, вместо этого методу делегата предлагается работать со строками. Для обнаружения фактического нажатия клавиши могут потребоваться некоторые хуки UIEvent/RunLoop.

Обратите внимание, что пустая строка, переданная textField(_,shouldChangeCharactersIn:,replacementString:), не всегда означает, что был нажат Backspace, операция вырезания также может привести к отправке пустой строки делегату. Вы можете попробовать проверить диапазон и предположить, что для диапазона 1 пробел был нажат, однако пользователь также может вырезать один символ...

person Cristik    schedule 29.07.2018
comment
Идеальный ответ! большое спасибо! Я понял о чем вы говорите на 100%. Поэтому я обновлю свой код, сославшись на ваш ответ. - person AutumnSky; 01.08.2018
comment
@AutumnSky пара замечаний: добавление частей ответа на вопрос не является рекомендуемой практикой SO, разделы вопросов и ответов следует использовать по назначению. Во-вторых, пожалуйста, проверьте последний абзац, который я добавил сегодня, пустая строка не обязательно означает, что был нажат Backspace. - person Cristik; 02.08.2018
comment
Отличный ответ... Я использую его уже почти 2 года, и теперь ясно, что это полностью ошибочный "алгоритм", который работает случайно.... Вы можете использовать \\x, и он будет работать, потому что, как @Cristic указывает, что strcmp оценивает только первый элемент «экранированной последовательности» по пустому вводу - person eharo2; 01.07.2020
comment
Я могу сообщить, что используя: strcmp(char, x) // x = ASCII 120 и затем: if isBackSpace == -120 И это сработает... - person eharo2; 01.07.2020