Sie können UITextField Unterklasse und ein benutzerdefiniertes Feld erstellen, die nur dem Benutzer die Eingabe von Zahlen zu ermöglichen, indem ein Ziel zu Ihrem Objekt Hinzufügen controlEvents für mit einem Wahl editingChanged UI zu aktualisieren.
Zuerst kann Unterklasse UITextField:
class ExpirationField: UITextField {
var allowsExpiredDate = false
override func didMoveToSuperview() {
super.didMoveToSuperview()
placeholder = "MM/YY"
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
keyboardType = .numberPad
textAlignment = .center
editingChanged()
}
}
Wir müssen auch richtig Text des Feldes, indem sie alle sie flatMap auf der String-Darstellung von ihnen Int Umwandlung nicht Ziffern Zeichen Filterung Format und ein Array von Int Rückkehr im Bereich von 0 bis 9. Wir müssen den Schrägstrich abhängig von der Anzahl der Ziffern, die der Benutzer eingegeben hat, setzen, indem wir die Anzahl der Ziffern in der Zeichenfolge ändern. Da es sich um ein Ablauffeld handelt, müssen Sie auch prüfen, ob der vom Benutzer eingegebene Monat und das Jahr noch gültig sind. Lassen Sie also ExpirationField Monats- und Jahreseigenschaften hinzufügen, um ihren Wert zurückzugeben. Gleiches gilt für das Datum gilt, so dass wir es auf den aktuellen Monat und Jahr vergleichen, kann das Ablaufdatum zu überprüfen:
extension ExpirationField {
var string : String { return text ?? "" }
var numbers: [Int] { return string.characters.flatMap{ Int(String($0)) } }
var year: Int { return numbers.suffix(2).integer }
var month: Int { return numbers.prefix(2).integer }
func editingChanged() {
text = expirationFormatted
if text?.characters.count == 5 {
print("Month:", month, "Year:", year, "isValid:", isValid)
if !allowsExpiredDate && !isValid {
text = numbers.prefix(2).string + "/" + numbers.dropLast().suffix(1).string
}
} else {
print("isValid:", false)
switch numbers.count {
case 1 where numbers.integer > 1:
text = ""
case 2 :
if numbers.integer > 12 {
text = "1"
} else if numbers.integer == 0 {
text = "0"
}
case 3 where (numbers.last ?? 0) < 1 && !allowsExpiredDate:
text = numbers.dropLast().string
case 4 where year + 2000 < Date().year && !allowsExpiredDate:
text = numbers.prefix(2).string + "/" + numbers.dropLast().suffix(1).string
default:
break
}
}
if isValid {
layer.borderColor = UIColor.darkGray.cgColor
layer.cornerRadius = 3
layer.borderWidth = 1
} else {
layer.borderColor = UIColor.clear.cgColor
layer.borderWidth = 0
}
}
var expirationFormatted: String {
let numbers = self.numbers.prefix(4)
switch numbers.count {
case 1...2: return numbers.string
case 3: return numbers.prefix(2).string + "/" + numbers.suffix(1).string
case 4: return numbers.prefix(2).string + "/" + numbers.suffix(2).string
default: return ""
}
}
var isValid: Bool {
if string.characters.count < 5 { return false }
guard 1...12 ~= month else {
print("invalid month:", month)
return false
}
guard Date().year-2000...99 ~= year else {
print("invalid year:", year)
return false
}
return year > Date().year-2000 ? true : month >= Date().month
}
override func deleteBackward() {
text = numbers.dropLast().string
text = expirationFormatted
layer.borderColor = UIColor.clear.cgColor
layer.borderWidth = 0
}
}
extension Calendar {
static let iso8601 = Calendar(identifier: .iso8601)
}
extension Date {
var year: Int {
return Calendar.iso8601.component(.year, from: self)
}
var month: Int {
return Calendar.iso8601.component(.month, from: self)
}
}
extension Collection where Iterator.Element == Int {
var string: String {
return map(String.init).joined()
}
var integer: Int { return reduce(0){ 10 * $0 + $1 } }
}
Dann ziehen Sie einfach ein Textfeld Ihrer Ansicht nach auswählen und benutzerdefinierte Klasse ExpirationField im Inspektor festgelegt werden:
Sample
Sie könnten immer zwei 'UITextField' mit einer Beschriftung haben, die"/"dazwischen zeigt, und verwenden Sie die gleiche Logik, um firstResponder status zu wechseln – Russell