Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AlexZverusha/2000e78db6b3ae00e46048068ad5022c to your computer and use it in GitHub Desktop.
Save AlexZverusha/2000e78db6b3ae00e46048068ad5022c to your computer and use it in GitHub Desktop.
Custom TextField with validation and animation
import UIKit
enum typeTextField {
case email
case password
case text
}
enum validationStatus {
case wrongEmail
case wrongPassword
case emptyField
case success
}
class TextField: UITextField, UITextFieldDelegate {
var colorPlace = UIColor.red
var textPlace: String?
var lineWidth: CGFloat?
var typeField: typeTextField = .text {
didSet {
switch typeField {
case .email:
keyboardType = .emailAddress
isSecureTextEntry = false
case .password:
keyboardType = .default
isSecureTextEntry = true
default:
keyboardType = .default
isSecureTextEntry = false
}
}
}
override func draw(_ rect: CGRect) {
let startingPoint = CGPoint(x: rect.minX, y: rect.maxY)
let endingPoint = CGPoint(x: rect.maxX, y: rect.maxY)
let path = UIBezierPath()
path.move(to: startingPoint)
path.addLine(to: endingPoint)
path.lineWidth = lineWidth ?? 2.0
tintColor.setStroke()
path.stroke()
}
@IBInspectable var placeHolderColor: UIColor? {
get {
return self.placeHolderColor
}
set {
self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ? self.placeholder! : "", attributes:[NSForegroundColorAttributeName: newValue!])
}
}
func showError() {
delegate = self
self.shake()
}
@discardableResult
func validate() -> validationStatus {
switch typeField {
case .email:
if (!isEmailValid()) {
showError()
return .wrongEmail
} else {
return .success
}
case .password:
if (!isPasswordValid()) {
showError()
return .wrongPassword
} else {
return .success
}
case .text:
if (text?.isEmpty == true) {
showError()
return .emptyField
} else {
return .success
}
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
self.validate()
}
func shake() {
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.duration = 0.6
animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
layer.add(animation, forKey: "shake")
}
// MARK: - Input Data Validation Logic
func isEmailValid() -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
return emailTest.evaluate(with: self.text)
}
func isPasswordValid() -> Bool {
guard let text = text else { return false }
return !text.isEmpty && text.characters.count >= 6
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment