传递到shouldChangeCharacters
的范围指的是更改前文本字段的文本范围.通常使用键盘插入文本时,范围的长度为0,replacementString
是您try 插入的字符.其 idea 是用新字符替换文本的空白区域,从而"插入"该字符.
因此,将该范围替换为占位符字符串的" "
,将在占位符字符串中插入一个空格.
您应该在文本字段的文本上使用它,而不是对占位符字符串使用给定的范围.无论如何,这就是means的范围.
插入后,您可以通过执行以下操作来计算文本字段的新文本:
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
}
从外观上看,您还希望每3位数字自动添加空格.
要做到这一点,您需要设置textField.text
:
// after the newText.count > placeHolderLabelString.count check
let spacesRemoved = newText.replacingOccurrences(of: " ", with: "")
textField.text = spacesRemoved.inserting(separator: " ", every: 3)
有关inserting(separator:every:)
的实现,请参见this answer.你可以用另一种方式做这件事.
然后,代码的其余部分应该替换placeHolderLabelString
的前textField.text!.count
个字符,而不是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