diff --git a/AnimatedField/Classes/AnimatedField+TextFieldDelegate.swift b/AnimatedField/Classes/AnimatedField+TextFieldDelegate.swift index 94c37ae..267cc56 100644 --- a/AnimatedField/Classes/AnimatedField+TextFieldDelegate.swift +++ b/AnimatedField/Classes/AnimatedField+TextFieldDelegate.swift @@ -17,8 +17,10 @@ extension AnimatedField: UITextFieldDelegate { return shouldChange } + let sstring = string.toEnglish() + // Copy new character - var newInput = string + var newInput = sstring // Replace special characters in newInput newInput = newInput.replacingOccurrences(of: "`", with: "") @@ -43,7 +45,7 @@ extension AnimatedField: UITextFieldDelegate { if !newInput.isValidWithRegEx(regex) && newInput != "" { return false } // Change textfield in manual mode in case of changing newInput. Check limits also - if newInput != string { + if newInput != sstring { textField.text = textField.text?.count ?? 0 + newInput.count <= limit ? "\(textField.text ?? "")\(newInput)" : textField.text return false } diff --git a/AnimatedField/Classes/AnimatedField.swift b/AnimatedField/Classes/AnimatedField.swift index 319082e..76d5c1b 100644 --- a/AnimatedField/Classes/AnimatedField.swift +++ b/AnimatedField/Classes/AnimatedField.swift @@ -44,6 +44,7 @@ open class AnimatedField: UIView { private var datePicker: UIDatePicker? private var initialDate: Date? private var dateFormat: String? + private var isPersian: Bool = true /// Picker values private var numberPicker: UIPickerView? @@ -109,10 +110,10 @@ open class AnimatedField: UIView { /// Field type (default values) public var type: AnimatedFieldType = .none { didSet { - if case let AnimatedFieldType.datepicker(mode, defaultDate, minDate, maxDate, chooseText, format) = type { + if case let AnimatedFieldType.datepicker(mode, defaultDate, minDate, maxDate, chooseText, format, bgColor, isPersian) = type { initialDate = defaultDate dateFormat = format - setupDatePicker(mode: mode, minDate: minDate, maxDate: maxDate, chooseText: chooseText) + setupDatePicker(mode: mode, minDate: minDate, maxDate: maxDate, chooseText: chooseText, bgColor: bgColor, isPersian: isPersian) } if case let AnimatedFieldType.numberpicker(defaultNumber, minNumber, maxNumber, chooseText) = type { setupPicker(defaultNumber: defaultNumber, minNumber: minNumber, maxNumber: maxNumber, chooseText: chooseText) @@ -316,12 +317,26 @@ open class AnimatedField: UIView { layoutIfNeeded() } - private func setupDatePicker(mode: UIDatePicker.Mode?, minDate: Date?, maxDate: Date?, chooseText: String?) { + private func setupDatePicker(mode: UIDatePicker.Mode?, minDate: Date?, maxDate: Date?, chooseText: String?, bgColor: UIColor?, isPersian: Bool = true) { datePicker = UIDatePicker() datePicker?.datePickerMode = mode ?? .date + if #available(iOS 13.4, *) { + datePicker?.preferredDatePickerStyle = .wheels + } else { + // Fallback on earlier versions + } + self.isPersian = isPersian datePicker?.maximumDate = maxDate datePicker?.minimumDate = minDate datePicker?.setValue(format.textColor, forKey: "textColor") + if isPersian { + datePicker?.datePickerMode = .date + datePicker?.calendar = Calendar(identifier: .persian) + datePicker?.locale = Locale(identifier: "fa_IR") + } + if let bgcolor = bgColor { + datePicker?.backgroundColor = bgcolor + } let toolBar = UIToolbar(target: self, selector: #selector(didChooseDatePicker)) @@ -366,9 +381,9 @@ open class AnimatedField: UIView { delegate?.animatedFieldDidChange(self) } - @objc func didChooseDatePicker() { + @objc func didChooseDatePicker(sender: Any) { let date = datePicker?.date ?? initialDate - textField.text = date?.format(dateFormat: dateFormat ?? "dd / MM / yyyy") + textField.text = date?.format(dateFormat: dateFormat ?? "dd / MM / yyyy", isPersian: isPersian) _ = resignFirstResponder() } diff --git a/AnimatedField/Classes/AnimatedFieldType.swift b/AnimatedField/Classes/AnimatedFieldType.swift index adf16c0..268a0a8 100644 --- a/AnimatedField/Classes/AnimatedFieldType.swift +++ b/AnimatedField/Classes/AnimatedFieldType.swift @@ -16,9 +16,11 @@ public enum AnimatedFieldType { case password(Int, Int) // min, max case price(Double, Int) // max price, max decimals case url - case datepicker(UIDatePicker.Mode?, Date?, Date?, Date?, String?, String?) // mode, default date, min date, max date, choose text, date format + case datepicker(UIDatePicker.Mode?, Date?, Date?, Date?, String?, String?, UIColor?, Bool) // mode, default date, min date, max date, choose text, date format case numberpicker(Int, Int, Int, String?) // default number, min number, max number, choose text case multiline + case numeric + case iranianCellphoneNumber var decimal: String { var separator = Locale.current.decimalSeparator ?? "\\." @@ -31,6 +33,8 @@ public enum AnimatedFieldType { case .email: return "[A-Z0-9a-z@_\\.]" case .username: return "[A-Za-z0-9_.]" case .price: return "[0-9\(decimal)]" + case .numeric: return "[0-9]" + case .iranianCellphoneNumber: return "[0-9]" default: return ".*" } } @@ -42,6 +46,8 @@ public enum AnimatedFieldType { case .password(let min, let max): return ".{\(min),\(max)}" case .price(_, let max): return "^(?=.*[1-9])([1-9]\\d*(?:\(decimal)\\d{1,\(max)})?|(?:0\(decimal)\\d{1,\(max)}))$" case .url: return "https?:\\/\\/(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?:\\/\\/(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,}" + case .numeric: return "[0-9]" + case .iranianCellphoneNumber: return "^(0)?9\\d{9}$" default: return ".*" } } @@ -53,6 +59,8 @@ public enum AnimatedFieldType { case .password: return "Password is not valid!" case .price: return "Price is not valid!" case .url: return "Url is not valid!" + case .numeric: return "Number is not valid!" + case .iranianCellphoneNumber: return "Cellphone number is not valid!" default: return "" } } diff --git a/AnimatedField/Classes/Extensions/Date+Format.swift b/AnimatedField/Classes/Extensions/Date+Format.swift index c804d93..7cee45d 100644 --- a/AnimatedField/Classes/Extensions/Date+Format.swift +++ b/AnimatedField/Classes/Extensions/Date+Format.swift @@ -9,8 +9,12 @@ import Foundation extension Date { - func format(dateFormat: String) -> String { + func format(dateFormat: String, isPersian: Bool) -> String { let dateFormatter = DateFormatter() + if isPersian { + dateFormatter.calendar = Calendar(identifier: .persian) + dateFormatter.locale = Locale(identifier: "fa_IR") + } dateFormatter.dateFormat = dateFormat return dateFormatter.string(from: self) } diff --git a/AnimatedField/Classes/Extensions/String+RegEx.swift b/AnimatedField/Classes/Extensions/String+RegEx.swift index dba87d3..e70f3eb 100644 --- a/AnimatedField/Classes/Extensions/String+RegEx.swift +++ b/AnimatedField/Classes/Extensions/String+RegEx.swift @@ -13,4 +13,25 @@ extension String { let pred = NSPredicate(format:"SELF MATCHES %@", regEx) return pred.evaluate(with: self) } + + func toEnglish() -> String { + let dic = [ + "۰" : "0", + "۱" : "1" , + "۲" : "2", + "۳" : "3", + "۴" : "4", + "۵" : "5" , + "۶" : "6", + "۷" : "7", + "۸" : "8", + "۹" : "9" + ] as Dictionary + + var result : String = self + for (key, value) in dic { + result = result.replacingOccurrences(of: key, with: value) + } + return result + } } diff --git a/Example/AnimatedField/ViewController.swift b/Example/AnimatedField/ViewController.swift index 31cbcc7..a69c18e 100644 --- a/Example/AnimatedField/ViewController.swift +++ b/Example/AnimatedField/ViewController.swift @@ -67,7 +67,7 @@ class ViewController: UIViewController { let maxDate = Date().addingTimeInterval(-13 * 365 * 24 * 60 * 60) let chooseText = "Choose" let dateFormat = "dd / MM / yyyy" - birthdateAnimatedField.type = .datepicker(.dateAndTime, defaultDate, minDate, maxDate, chooseText, dateFormat) + birthdateAnimatedField.type = .datepicker(.dateAndTime, defaultDate, minDate, maxDate, chooseText, dateFormat, .black, true) birthdateAnimatedField.tag = 2 numberAnimatedField.format = format