Я пытаюсь добиться изображения ниже:
Как вы можете видеть на изображении, когда пользователь вводит число в текстовое поле, другие цифры числа по-прежнему используются в качестве заполнителя. (000 000 0000)
Для этого я поместил UILabel внутри UITextField.
var placeHolderLabelString = "___ ___ ____"
var placeholderLabel = UILabel()
placeholderLabel.text = placeHolderLabelString
placeholderLabel.sizeToFit()
numberInputView.addSubview(placeholderLabel)
placeholderLabel.textColor = .gray
placeholderLabel.font = numberInputView.font
Я хочу удалить каждое подчеркивание, когда пользователь вводит цифру в текстовое поле. Я пробовал следующий код:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let rnd = Range(range, in: placeHolderLabelString)!
placeHolderLabelString = placeHolderLabelString.replacingCharacters(in: rnd, with: " ")
placeholderLabel.text = placeHolderLabelString
return true
}
Но это не работает. Он добавляет пробел в начало placeHolderLabelString, а не заменяет его. Как мне это сделать?





Диапазон, переданный shouldChangeCharacters, относится к диапазону текста текстового поля до изменения. Когда вы обычно вставляете текст с помощью клавиатуры, диапазон имеет длину 0, а replacementString — это символ, который вы пытаетесь вставить. Идея состоит в том, что вы заменяете пустой диапазон текста новым символом, следовательно, «вставляете» этот символ.
В результате замена того же диапазона на " " в строке-заполнителе приведет к вставке пробела в строку-заполнитель.
Вместо того, чтобы использовать заданный диапазон в строке-заполнителе, вы должны использовать его в тексте текстового поля. В любом случае, это то, что означает диапазон.
Вы можете вычислить новый текст текстового поля после вставки, выполнив:
let newText = (textField.text! as NSString).replacingCharacters(in: range, with: string)
Затем замените первые newText.count символы строки-заполнителя пробелами. Установите это как новый текст метки-заполнителя.
// note that I changed this to a let, because I do not change the placeholder string
let placeHolderLabelString = "___ ___ ___"
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let newText = (textField.text! as NSString).replacingCharacters(in: range, with: string)
// do not allow more text than the placeholder
if newText.count > placeHolderLabelString.count {
return false
}
let startIndex = placeHolderLabelString.startIndex
let replaceableRange = startIndex..<placeHolderLabelString.index(startIndex, offsetBy: newText.count)
let newPlaceholder = placeHolderLabelString.replacingCharacters(
in: replaceableRange, with: String(repeating: " ", count: newText.count)
)
placeholderLabel.text = newPlaceholder
return true
}
Судя по всему, вы также хотите автоматически добавлять пробелы в некоторых местах.
Для этого вам нужно установить textField.text:
// after the newText.count > placeHolderLabelString.count check
let spacesRemoved = newText.replacingOccurrences(of: " ", with: "")
textField.text = formatPhoneNumber(spacesRemoved)
где formatPhoneNumber — метод, который правильно вставляет пробелы. Его реализация оставлена читателю в качестве упражнения.
Затем остальная часть кода должна заменить первые textField.text!.count символы placeHolderLabelString, а не newText.count. Потому что newText больше не является текстом в текстовом поле.
let startIndex = placeHolderLabelString.startIndex
// note that I'm using textField.text instead of newText here,
// because *that* is actually the text of the text field now
let replaceableRange = startIndex..<placeHolderLabelString.index(startIndex, offsetBy: textField.text!.count)
let newPlaceholder = placeHolderLabelString.replacingCharacters(
in: replaceableRange, with: String(repeating: " ", count: newText.count)
)
placeholderLabel.text = newPlaceholder
// the text field's text should not change, because we set it programmatically to the desired value already.
return false
К сведению: заполнителю нужно 4 символа подчеркивания в 3-й группе, а не 3. И все это предполагает, что вы хотите поддерживать только телефонные номера США/Канады. shouldChangeCharactersIn также необходимо убедиться, что вводятся только цифры. Эти надоедливые пользователи могут попытаться вставить любой случайный текст.
@HangarRash Ты прав. Я неправильно понял заполнитель, думая, что там всего 9 цифр. Следить за тем, чтобы вводились только цифры, остается в качестве упражнения для читателя :). Об этом уже много сообщений, и я чувствовал, что мой ответ становится длинным. OP мог бы отключить вставку, насколько нам известно.
Вау, это потрясающее объяснение. Большое спасибо :)