Further swiftification.

This commit is contained in:
Kevin G Christiano 2019-10-11 13:23:49 -04:00
parent ef2e177b33
commit d4df5745f4

View File

@ -18,7 +18,7 @@ import UIKit
@objc optional func dismissFieldInput(_ sender: Any?)
}
@objcMembers open class TextField: ViewConstrainingView, MVMCoreUIMoleculeViewProtocol, FormValidationProtocol {
@objcMembers open class TextField: ViewConstrainingView {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
@ -30,41 +30,57 @@ import UIKit
var separatorView: UIView?
var view: UIView?
/// If you're using a MFViewController, you must set this to it
weak var mfTextFieldDelegate: MFTextFieldDelegate?
// The delegate and block for validation. Validates if the text that the user has entered is valid or not. Checked after each change if there is a delegate.
var uiTextFieldDelegate: UITextFieldDelegate? {
get {
return textField?.delegate
}
set (newValue) {
textField?.delegate = newValue
}
}
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
weak var text: String?
weak var formText: String?
weak var fieldKey: String?
weak var placeholder: String?
weak var label: UILabel?
// If you're using a MFViewController, you must set this to it
weak var uiTextFieldDelegate: UITextFieldDelegate?
// The delegate and block for validation. Validates if the text that the user has entered is valid or not. Checked after each change if there is a delegate.
weak var mfTextFieldDelegate: MFTextFieldDelegate?
//accesories
weak var pickerView: UIPickerView?
//utility
var observingForChanges = false
var errorShowing = false
var hasDropDown = false
/*make it public so outsider class can know the posistion of it. */
var dashLine: DashLine?
var dropDownCarrotLabel: UILabel?
var dropDownCarrotWidth: NSLayoutConstraint?
var text: String?
var formText: String?
var fieldKey: String?
var placeholder: String?
var enabled = false
// To set the placeholder and text
/* will move out in Feb release */
var hideBorder = false
weak var datePicker: UIDatePicker?
private(set) weak var toolbar: UIToolbar?
//helper
var formatter: DateFormatter?
var valid = false
var validationBlock: ((_ enteredValue: String?) -> Bool)?
// custom text colors
var customEnabledTextColor: UIColor?
var customDisabledTextColor: UIColor?
//default error message
var errMessage: String?
var editCompleteAction: ((_ text: String?) -> ())?
@ -91,72 +107,47 @@ import UIKit
public override init(frame: CGRect) {
super.init(frame: frame)
translatesAutoresizingMaskIntoConstraints = false
}
required public init?(coder: NSCoder) {
super.init(coder: coder)
fatalError("init(coder:) has not been implemented")
}
public convenience init() {
self.init(frame: .zero)
hasDropDown = false
}
public convenience init(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
self.init(frame: .zero)
mfTextFieldDelegate = delegate
uiTextFieldDelegate = delegate
}
/*
public convenience init() {
self.init(frame: .zero)
dropDownCarrotLabel().hidden = false
hasDropDown = false
}
public convenience init(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
self.init(frame: .zero)
bothTextFieldDelegates = delegate
}
public convenience init(withMap map: [AnyHashable : Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
self.init(frame: .zero)
translatesAutoresizingMaskIntoConstraints = false
setWithMap(map, bothDelegates: delegate)
}
public convenience init(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
self.init(frame: .zero)
bothTextFieldDelegates = delegate
}
*/
class func mfTextField() -> Self? {
public convenience init(withMap map: [AnyHashable: Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
self.init(frame: .zero)
let view = self.init()
view?.hasDropDown = false
return view
setWithMap(map, bothDelegates: delegate)
}
public convenience init(mfTextFieldForDropDown: Bool) {
self.init(frame: .zero)
dropDownCarrotLabel?.isHidden = false
hasDropDown = true
}
class func mfTextField(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
public convenience init(mfTextFieldForDropDownWithMap map: [AnyHashable: Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
self.init(frame: .zero)
let textField = self.mfTextField()
textField?.bothTextFieldDelegates = delegate
return textField
}
class func mfTextField(withMap map: [AnyHashable : Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
let textField = self.mfTextField()
textField?.translatesAutoresizingMaskIntoConstraints = false
textField?.setWithMap(map, bothDelegates: delegate)
return textField
}
class func mfTextFieldForDropDown() -> Self? {
let textField = self.mfTextField()
textField?.dropDownCarrotLabel().hidden = false
textField?.hasDropDown = true
return textField
}
class func mfTextFieldForDropDown(withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
let textField = self.mfTextFieldForDropDown()
textField?.bothTextFieldDelegates = delegate
return textField
dropDownCarrotLabel?.isHidden = false
hasDropDown = true
setWithMap(map, bothDelegates: delegate)
}
//--------------------------------------------------
@ -169,59 +160,59 @@ import UIKit
translatesAutoresizingMaskIntoConstraints = false
backgroundColor = .clear
backgroundColor = .clear
let view = views?.first as? UIView
view?.translatesAutoresizingMaskIntoConstraints = false
view?.setContentHuggingPriority(.required, for: .vertical)
view?.setContentCompressionResistancePriority(.required, for: .vertical)
self.view = view
view?.frame = frame
if let view = view {
addSubview(view)
}
pinView(toSuperView: view)
textField.font = MFStyler.fontForTextField()
translatesAutoresizingMaskIntoConstraints = false
formLabel.font = MFStyler.fontB3()
formLabel.textColor = UIColor.mfBattleshipGrey()
label.font = MFStyler.fontForTextFieldUnderLabel()
label.textColor = UIColor.black
dropDownCarrotLabel.hidden = true
separatorView.backgroundColor = UIColor.black
dashLine.backgroundColor = UIColor.white
dashLine.hidden = true
MFStyler.styleTextField(textField)
dropDownCarrotLabel.isUserInteractionEnabled = true
let tapOnCarrot = UITapGestureRecognizer(target: self, action: #selector(startEditing))
dropDownCarrotLabel.addGestureRecognizer(tapOnCarrot)
enabled = true
// Disable SmartQuotes
if #available(iOS 11.0, *) {
textField.smartQuotesType = .no
textField.smartDashesType = .no
textField.smartInsertDeleteType = .no
}
let view = views?.first as? UIView
view?.translatesAutoresizingMaskIntoConstraints = false
view?.setContentHuggingPriority(.required, for: .vertical)
view?.setContentCompressionResistancePriority(.required, for: .vertical)
self.view = view
view?.frame = frame
if let view = view {
addSubview(view)
}
pinView(toSuperView: view)
textField?.font = MFStyler.fontForTextField()
translatesAutoresizingMaskIntoConstraints = false
formLabel?.font = MFStyler.fontB3()
formLabel?.textColor = UIColor.mfBattleshipGrey()
label?.font = MFStyler.fontForTextFieldUnderLabel()
label?.textColor = UIColor.black
dropDownCarrotLabel?.isHidden = true
separatorView?.backgroundColor = UIColor.black
dashLine?.backgroundColor = UIColor.white
dashLine?.isHidden = true
MFStyler.styleTextField(textField!)
dropDownCarrotLabel?.isUserInteractionEnabled = true
let tapOnCarrot = UITapGestureRecognizer(target: self, action: #selector(startEditing))
dropDownCarrotLabel?.addGestureRecognizer(tapOnCarrot)
enabled = true
// Disable SmartQuotes
if #available(iOS 11.0, *) {
textField?.smartQuotesType = .no
textField?.smartDashesType = .no
textField?.smartInsertDeleteType = .no
}
}
func updateView(_ size: CGFloat) {
open override func updateView(_ size: CGFloat) {
super.updateView(size)
DispatchQueue.main.async { [weak self] in
self?.formLabel?.updateView(size)
self?.label.font = MFStyler.fontForTextFieldUnderLabel()
let textField = self?.textField {
MFStyler.styleTextField(textField)
}
self?.dashLine.updateView(size)
self?.label?.font = MFStyler.fontForTextFieldUnderLabel()
// let textFieldView = {
MFStyler.styleTextField(self!.textField!)
// }
self?.dashLine?.updateView(size)
}
}
@ -230,28 +221,23 @@ import UIKit
uiTextFieldDelegate = nil
}
func draw(_ rect: CGRect) {
open override func draw(_ rect: CGRect) {
super.draw(rect)
borderPath.removeAllPoints()
borderPath?.removeAllPoints()
if !hideBorder {
let frame = textFieldContainerView.frame
borderPath = UIBezierPath()
borderPath.move(to: CGPoint(x: frame.origin.x, y: frame.origin.y + frame.size.height))
borderPath.addLine(to: CGPoint(x: frame.origin.x, y: frame.origin.y))
borderPath.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y))
borderPath.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y + frame.size.height))
let frame = textFieldContainerView!.frame
borderPath = UIBezierPath()
borderPath?.move(to: CGPoint(x: frame.origin.x, y: frame.origin.y + frame.size.height))
borderPath?.addLine(to: CGPoint(x: frame.origin.x, y: frame.origin.y))
borderPath?.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y))
borderPath?.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y + frame.size.height))
borderPath?.lineWidth = 1
var strokeColor: UIColor?
if errorShowing {
strokeColor = UIColor.mfPumpkin()
} else {
strokeColor = UIColor.mfSilver()
}
strokeColor?.setStroke()
let strokeColor = errorShowing ? UIColor.mfPumpkin() : UIColor.mfSilver()
strokeColor.setStroke()
borderPath?.stroke()
}
}
@ -260,6 +246,14 @@ import UIKit
// MARK: - Methods
//--------------------------------------------------
func placeholder() -> String? {
return textField.attributedPlaceholder.string
}
func text() -> String? {
return textField.text()
}
// MARK: - Utilities
func createDatePicker() {
//tool bar
@ -302,12 +296,12 @@ import UIKit
}
func dismissDatePicker() -> Date? {
let pickedDate = datePicker!.date
if let pickedDate = pickedDate {
if calendar.isDate(pickedDate, inSameDayAs: Date()) {
var pickedDate = datePicker!.date
if let pickedDatei = pickedDate {
if calendar.isDate(pickedDatei, inSameDayAs: Date()) {
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
} else {
self.text = formatter.string(from: pickedDate)
self.text = formatter.string(from: pickedDatei)
}
}
textField?.resignFirstResponder()
@ -325,9 +319,9 @@ import UIKit
self?.separatorHeightConstraint?.constant = 4
self?.errorShowing = true
self?.separatorView?.backgroundColor = UIColor.mfPumpkin()
self?.label.text() = errorMessage
self?.label.numberOfLines = 0
self?.textField.accessibilityValue() = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message"), self.textField.text() ?? "", errorMessage ?? "")
self?.label?.text = errorMessage
self?.label?.numberOfLines = 0
self?.textField?.accessibilityValue() = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message"), self.textField.text() ?? "", errorMessage ?? "")
self?.setNeedsDisplay()
self?.layoutIfNeeded()
}
@ -336,7 +330,7 @@ import UIKit
func pushAccessibilityNotification() {
DispatchQueue.main.async { [weak self] in
UIAccessibilityPostNotification(UIAccessibility.Notification.layoutChanged, self?.textField)
UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: self?.textField)
}
}
@ -347,22 +341,14 @@ import UIKit
self?.separatorView?.backgroundColor = UIColor.black
self?.layoutIfNeeded()
self?.errorShowing = false
self?.label.textColor = UIColor.black
self?.label.text() = ""
self?.label?.textColor = UIColor.black
self?.label?.text = ""
self?.textField?.accessibilityValue = nil
self?.setNeedsDisplay()
self?.layoutIfNeeded()
}
}
func placeholder() -> String? {
return textField.attributedPlaceholder.string
}
func text() -> String? {
return textField.text()
}
// MARK: - Setters
func setPlaceholder(_ placeholder: String?, with color: UIColor?) {
@ -375,10 +361,10 @@ import UIKit
])
}
}
if textField.text.length > 0 && !errorShowing {
label.text = placeholder
if textField?.text.length > 0 && !errorShowing {
label?.text = placeholder
} else if !errorShowing {
label.text = ""
label?.text = ""
}
setAccessibilityString(placeholder)
}
@ -430,7 +416,7 @@ import UIKit
}
func setUiTextFieldDelegate(_ uiTextFieldDelegate: UITextFieldDelegate?) {
self.uiTextFieldDelegate = uiTextFieldDelegate
uiTextFieldDelegate = uiTextFieldDelegate
textField?.delegate = uiTextFieldDelegate
}
@ -462,19 +448,22 @@ import UIKit
}
string = map?.string(KeyErrorMessage)
if (string?.count ?? 0) > 0 {
errMessage = string
}
// key used to send text value to server
string = map?.string(KeyFieldKey)
if (string?.count ?? 0) > 0 {
fieldKey = string
}
string = map?.string(KeyType)
if (string == "dropDown") {
dropDownCarrotLabel().hidden = false
dropDownCarrotLabel?.isHidden = false
self.hasDropDown = true
} else if (string == "password") {
@ -488,6 +477,7 @@ import UIKit
}
string = map?.string("regex")
if (string?.count ?? 0) != 0 {
validationBlock = { enteredValue in
return MVMCoreUIUtility.validate(enteredValue, withRegularExpression: string)
@ -499,7 +489,8 @@ import UIKit
func setWithMap(_ map: [AnyHashable : Any]?, bothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) {
MVMCoreUICommonViewsUtility.addDismissToolbar(textField!, delegate: delegate)
self.bothTextFieldDelegates = delegate
uiTextFieldDelegate = delegate
textFieldDelegate = delegate
setWithMap(map)
}
@ -510,35 +501,29 @@ import UIKit
func setDefaultValidationBlock() {
self.validationBlock = { enteredValue in
if (enteredValue?.count ?? 0) > 0 {
return true
} else {
return false
}
return (enteredValue?.count ?? 0) > 0
}
}
override func setLeftPinConstant(_ constant: CGFloat) {
open override func setLeftPinConstant(_ constant: CGFloat) {
textContainerLeftPin?.constant = constant
errorLableLeftPin?.constant = constant
formLabelLeftPin?.constant = constant
}
func setRightPinConstant(_ constant: CGFloat) {
open override func setRightPinConstant(_ constant: CGFloat) {
textContainerRightPin?.constant = constant
errorLableRightPin?.constant = constant
formLabelRightPin?.constant = constant
}
//--------------------------------------------------
// MARK: - XIB Helpers
//--------------------------------------------------
func showDropDown(_ show: Bool) {
if hasDropDown {
dropDownCarrotLabel.hidden = !show
dropDownCarrotWidth.active = !show
dropDownCarrotLabel?.isHidden = !show
dropDownCarrotWidth?.isActive = !show
setNeedsLayout()
layoutIfNeeded()
}
@ -548,41 +533,41 @@ import UIKit
enabled = enable //Set outside the dispatch so that registerAnimations can know about it
DispatchQueue.main.async { [weak self] in
self?.isUserInteractionEnabled = enable
self?.textField.userInteractionEnabled = enable
self?.textField.isEnabled = enable
self?.textField?.isUserInteractionEnabled = enable
self?.textField?.isEnabled = enable
if enable {
self?.textField.textColor = self.customEnabledTextColor ?? .black
self?.formLabel.textColor = UIColor.mfBattleshipGrey()
self?.label.textColor = UIColor.black
self?.textField?.textColor = self?.customEnabledTextColor ?? .black
self?.formLabel?.textColor = UIColor.mfBattleshipGrey()
self?.label?.textColor = UIColor.black
if self!.errorShowing {
self?.separatorView.backgroundColor = UIColor.mfPumpkin()
self?.separatorView?.backgroundColor = UIColor.mfPumpkin()
} else {
self?.separatorView.backgroundColor = .black
self?.separatorView?.backgroundColor = .black
}
self?.showDropDown(true)
} else {
self?.textField.textColor = self!.customDisabledTextColor ?? UIColor.mfSilver()
self?.formLabel.textColor = UIColor.mfSilver()
self?.label.textColor = UIColor.mfSilver()
self?.textField?.textColor = self!.customDisabledTextColor ?? UIColor.mfSilver()
self?.formLabel?.textColor = UIColor.mfSilver()
self?.label?.textColor = UIColor.mfSilver()
self?.showDropDown(false)
self?.hideError() //should not have error if the field is disabled
self?.separatorView.backgroundColor = UIColor.mfSilver()
self?.separatorView?.backgroundColor = UIColor.mfSilver()
}
}
}
func showLabel(_ show: Bool) {
label?.hidden = !show
label?.isHidden = !show
}
func dashSeperatorView(_ dash: Bool) {
if dash {
dashLine?.hidden = false
dashLine?.isHidden = false
//never hide seperator view because it could be possiblely used by other classes for positioning
separatorView?.backgroundColor = .clear
} else {
dashLine?.hidden = true
separatorView.backgroundColor = .black
dashLine?.isHidden = true
separatorView?.backgroundColor = .black
}
}
@ -603,7 +588,7 @@ import UIKit
// Check validity.
let previousValidity = valid
if validationBlock {
if (validationBlock != nil) {
valid = validationBlock(text)
} else {
//if validation not set, input will always be valid
@ -611,7 +596,7 @@ import UIKit
}
if previousValidity && !valid {
if errMessage {
if (errMessage != nil) {
self.errorMessage = errMessage
}
if mfTextFieldDelegate.responds(to: #selector(entryIsInvalid(_:))) {
@ -653,29 +638,13 @@ import UIKit
}
return enabledTextFields
}
}
// MARK: - Molecular
extension TextField {
//--------------------------------------------------
// MARK: - Accessibility
//--------------------------------------------------
func formatter() -> DateFormatter? {
if !formatter {
formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeZone = NSTimeZone.system
formatter.locale = NSLocale.current
formatter.formatterBehavior = .default
}
return formatter
}
//--------------------------------------------------
// MARK: - Molecular
//--------------------------------------------------
override open func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
if (delegateObject is MVMCoreUIDelegateObject) {
FormValidator.setupValidation(withMolecule: self, delegate: delegateObject?.formValidationProtocol)
let formValidator = FormValidator.getForDelegate(delegateObject?.formValidationProtocol)
@ -683,17 +652,32 @@ import UIKit
self.withMap = json
mfTextFieldDelegate = formValidator
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate)
MVMCoreUICommonViewsUtility.addDismissToolbar(textField!, delegate: uiTextFieldDelegate)
}
}
override open class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return 76
}
}
// MARK: - Accessibility
extension TextField {
//--------------------------------------------------
// MARK: - Form Validation
//--------------------------------------------------
func formatter() -> DateFormatter? {
if !formatter {
formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeZone = .system
formatter.locale = .current
formatter.formatterBehavior = .default
}
return formatter
}
}
// MARK: - Form Validation
extension TextField: FormValidationProtocol {
public func isValidField() -> Bool {
return isValid