我正在努力实现以下形象:

enter image description here

正如您在图像中所看到的,当用户在文本字段中键入数字时,该数字的其他数字仍然是占位符.(000 000 0000)

为此,我在UITextfield中放置了一个UILabel.

var placeHolderLabelString = "___ ___ ____"
var placeholderLabel = UILabel()
placeholderLabel.text = placeHolderLabelString
placeholderLabel.sizeToFit()
numberInputView.addSubview(placeholderLabel)
placeholderLabel.textColor = .gray
placeholderLabel.font = numberInputView.font

当用户在文本字段中键入数字时,我想删除每个下划线.我已经try 了以下代码:

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是您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

Ios相关问答推荐

Xcode版本15.2上未显示iOS 16.4的模拟器

如何在SwiftUI中扩展双击的可检测区域?

RFID scanner 的蓝牙服务 UUID?

保存和读取登录到 keys 串不工作 IOS swift

SwiftUI 故障/错误 - 在 LazyVStack 和 ScrollView 中使用 AVPlayer 时状态栏不显示

使用 SwiftUI 显示多个 VNRecognizedObjectObservation 边界框时偏移量错误

在 Swift 中 @MainActor 似乎被 withCheckedContinuation 而不是其他异步调用继承是巧合吗?

在左侧显示多行值时会出现 SwiftUI 错误,这会 destruct 堆栈中右侧的对齐方式

小部件链接有效,但不执行任何操作

SwiftUI:通过Sheet将数据添加到Realm DB时视图不更新

包装在 AnyView 中时 UIViewControllerRepresentable 无法正常工作

.overlay 和 body 是什么 swift 概念

如何在不同设备的segment控制中管理文本大小(text size)?

如何避免任何绑定空错误并更好地获取代码

如何在 Swift 上的 sendSynchronousRequest 中判断 Response.statusCode

iOS swift从另一个数组中删除一个数组的元素

在 Xcode 4 中将静态库链接到 iOS 项目

在 iOS 8.1 模拟器上更改语言不起作用

如何删除UITableView中最后一个单元格的最后一个边框?

用 NavigationViewController 快速呈现 ViewController