[英]Limit Text Field to one decimal point input, numbers only, and two characters after the decimal place - Swift 3
I am struggling to do this with Swift 3. I have a text field that I would like to limit to only numbers and one decimal point and two characters after the decimal place.我正在努力使用 Swift 3. 我有一个文本字段,我想将其限制为仅数字和一个小数点以及小数点后两个字符。 I would also like to have it work in regions where a decimal point is not used when entering non-integers.
我还想让它在输入非整数时不使用小数点的区域工作。 Thank you for any suggestions!
感谢您的任何建议!
You need to assign delegate to your textfield and in the shouldChangeCharactersIn delegate method do your validations:您需要将委托分配给您的文本字段,并在 shouldChangeCharactersIn 委托方法中进行验证:
Add extension with validation methods for the string:为字符串添加带有验证方法的扩展:
extension String{ private static let decimalFormatter:NumberFormatter = { let formatter = NumberFormatter() formatter.allowsFloats = true return formatter }() private var decimalSeparator:String{ return String.decimalFormatter.decimalSeparator ?? "." } func isValidDecimal(maximumFractionDigits:Int)->Bool{ // Depends on you if you consider empty string as valid number guard self.isEmpty == false else { return true } // Check if valid decimal if let _ = String.decimalFormatter.number(from: self){ // Get fraction digits part using separator let numberComponents = self.components(separatedBy: decimalSeparator) let fractionDigits = numberComponents.count == 2 ? numberComponents.last ?? "" : "" return fractionDigits.characters.count <= maximumFractionDigits } return false } }
In your delegate method:在您的委托方法中:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // Get text let currentText = textField.text ?? "" let replacementText = (currentText as NSString).replacingCharacters(in: range, with: string) // Validate return replacementText.isValidDecimal(maximumFractionDigits: 2) }
var number = Double(yourTextfield.text)
if number != nil {
//if user enters more than 2 digits after the decimal point it will round it up to 2
let roundedNumber = Double(num!).roundTo(places: 2)
}
else {
//probably print an error message
}
If you are using Swift UI then the complete solution如果您使用的是 Swift UI 那么完整的解决方案
File NumbersOnlyViewModifier文件编号OnlyViewModifier
import Foundation
import SwiftUI
import Combine
struct NumbersOnlyViewModifier: ViewModifier {
@Binding var text: String
var includeDecimal: Bool
var digitAllowedAfterDecimal: Int = 1
func body(content: Content) -> some View {
content
.keyboardType(includeDecimal ? .decimalPad : .numberPad)
.onReceive(Just(text)) { newValue in
var numbers = "0123456789"
let decimalSeparator: String = Locale.current.decimalSeparator ?? "."
if includeDecimal {
numbers += decimalSeparator
}
if newValue.components(separatedBy: decimalSeparator).count-1 > 1 {
let filtered = newValue
self.text = isValid(newValue: String(filtered.dropLast()), decimalSeparator: decimalSeparator)
} else {
let filtered = newValue.filter { numbers.contains($0)}
if filtered != newValue {
self.text = isValid(newValue: filtered, decimalSeparator: decimalSeparator)
} else {
self.text = isValid(newValue: newValue, decimalSeparator: decimalSeparator)
}
}
}
}
private func isValid(newValue: String, decimalSeparator: String) -> String {
guard includeDecimal, !text.isEmpty else { return newValue }
let component = newValue.components(separatedBy: decimalSeparator)
if component.count > 1 {
guard let last = component.last else { return newValue }
if last.count > digitAllowedAfterDecimal {
let filtered = newValue
return String(filtered.dropLast())
}
}
return newValue
}
}
File View+Extenstion文件查看+扩展
extension View {
func numbersOnly(_ text: Binding<String>, includeDecimal: Bool = false) -> some View {
self.modifier(NumbersOnlyViewModifier(text: text, includeDecimal: includeDecimal))
}
}
File ViewFile文件查看文件
TextField("\(count, specifier: Constants.FloatFormat.twoDecimalFloat)", text: $value, onEditingChanged: { isEditing in
self.isEditing = isEditing
})
.foregroundColor(Color.neutralGray900)
.numbersOnly($value, includeDecimal: true)
.font(.system(size: Constants.FontSizes.fontSize22))
.multilineTextAlignment(.center)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.