2017-03-25 4 views
0

Ich versuche, ein Ablauffeld zu formatieren, so dass es den Text wie folgt formatiert: MM/YY Ich kann das Textfeld die zusätzlichen Zeichen hinzufügen, wenn der Benutzer jedoch tippt Wenn ich komme, um die Zahlen zu löschen, erlaubt der Code Ihnen nicht, zwei Zeichen zu gehen, bevor Sie das "/" wieder hinzufügen. Gibt es einen Weg, den ich erkennen kann, wenn der Benutzer die Textfeldprüfung löscht und umgeht?Swift Format Textfeld, wenn der Benutzer tippt

ExpiryOutlet.addTarget(self, action: #selector(ExpiryDidChange(_:)), for: .editingChanged) 

func ExpiryDidChange(_ textField: UITextField) { 
    if textField == ExpiryOutlet { 

     if textField.text != "" && textField.text?.characters.count == 2 { 
      textField.text = "\(textField.text!)/" 
     } 

    } 
} 

Dank

+0

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

Antwort

0

Gibt es eine Möglichkeit, die ich erkennen kann, wenn der Benutzer die Textfeldprüfung löscht und umgeht?

Das Problem ist, dass Sie die falsche Methode implementiert haben. Implementieren Sie die Delegate-Methode text​Field(_:​should​Change​Characters​In:​replacement​String:​). Dadurch können Sie unterscheiden wo der Text ändert sich (der zweite Parameter ist der Bereich) und was der neue Text ist - im Fall der Rücktaste wird replacementString leer sein.

+0

Yup, dies löste es zusammen mit dem Erkennen eines Benutzers, der eine Nummer aus dem Textfeld löscht. – user7684436

1

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:

enter image description here

Sample

+0

Was ist der Sinn der Unterklasse? 'editChanged' benötigt nur ein Aktionsziel. – matt

+0

Was ist falsch mit Unterklassen? –

+0

Ich sagte nicht, dass etwas nicht stimmte. Aber es scheint völlig unnötig, warum also? – matt

Verwandte Themen