added inputentryfield
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
parent
273f45def0
commit
65be46c767
@ -579,6 +579,7 @@
|
|||||||
EA17584C2BC9894800A5C0D9 /* ButtonIconModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */; };
|
EA17584C2BC9894800A5C0D9 /* ButtonIconModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */; };
|
||||||
EA17584E2BC9895A00A5C0D9 /* ButtonIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */; };
|
EA17584E2BC9895A00A5C0D9 /* ButtonIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */; };
|
||||||
EA1B02DE2C41BFD200F0758B /* RuleVDSModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA1B02DD2C41BFD200F0758B /* RuleVDSModel.swift */; };
|
EA1B02DE2C41BFD200F0758B /* RuleVDSModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA1B02DD2C41BFD200F0758B /* RuleVDSModel.swift */; };
|
||||||
|
EA1B02E02C470AFD00F0758B /* InputEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA1B02DF2C470AFD00F0758B /* InputEntryField.swift */; };
|
||||||
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; };
|
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; };
|
||||||
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; };
|
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; };
|
||||||
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
|
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
|
||||||
@ -1201,6 +1202,7 @@
|
|||||||
EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconModel.swift; sourceTree = "<group>"; };
|
EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconModel.swift; sourceTree = "<group>"; };
|
||||||
EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = "<group>"; };
|
EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = "<group>"; };
|
||||||
EA1B02DD2C41BFD200F0758B /* RuleVDSModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleVDSModel.swift; sourceTree = "<group>"; };
|
EA1B02DD2C41BFD200F0758B /* RuleVDSModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleVDSModel.swift; sourceTree = "<group>"; };
|
||||||
|
EA1B02DF2C470AFD00F0758B /* InputEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputEntryField.swift; sourceTree = "<group>"; };
|
||||||
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||||
EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = "<group>"; };
|
EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = "<group>"; };
|
||||||
EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = "<group>"; };
|
EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = "<group>"; };
|
||||||
@ -2351,6 +2353,7 @@
|
|||||||
children = (
|
children = (
|
||||||
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */,
|
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */,
|
||||||
0A21DB7E235DECC500C160A2 /* EntryField.swift */,
|
0A21DB7E235DECC500C160A2 /* EntryField.swift */,
|
||||||
|
EA1B02DF2C470AFD00F0758B /* InputEntryField.swift */,
|
||||||
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */,
|
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */,
|
||||||
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */,
|
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */,
|
||||||
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */,
|
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */,
|
||||||
@ -3140,6 +3143,7 @@
|
|||||||
323AC96A24C837F000F8E4C4 /* ListThreeColumnBillChangesModel.swift in Sources */,
|
323AC96A24C837F000F8E4C4 /* ListThreeColumnBillChangesModel.swift in Sources */,
|
||||||
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */,
|
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */,
|
||||||
525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */,
|
525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */,
|
||||||
|
EA1B02E02C470AFD00F0758B /* InputEntryField.swift in Sources */,
|
||||||
D28BA730247EC2EB00B75CB8 /* NavigationButtonModelProtocol.swift in Sources */,
|
D28BA730247EC2EB00B75CB8 /* NavigationButtonModelProtocol.swift in Sources */,
|
||||||
0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */,
|
0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */,
|
||||||
D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */,
|
D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */,
|
||||||
|
|||||||
@ -0,0 +1,350 @@
|
|||||||
|
//
|
||||||
|
// InputEntryField.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Matt Bruce on 7/16/24.
|
||||||
|
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import VDS
|
||||||
|
|
||||||
|
@objcMembers open class InputEntryField: VDS.InputField, VDSMoleculeViewProtocol, ObservingTextFieldDelegate, ViewMaskingProtocol {
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//------------------------------------------------------
|
||||||
|
open var viewModel: TextEntryFieldModel!
|
||||||
|
open var delegateObject: MVMCoreUIDelegateObject?
|
||||||
|
open var additionalData: [AnyHashable : Any]?
|
||||||
|
|
||||||
|
// Form Validation
|
||||||
|
var fieldKey: String?
|
||||||
|
var fieldValue: JSONValue?
|
||||||
|
var groupName: String?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Stored Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
public var isValid: Bool = true
|
||||||
|
|
||||||
|
/// Holds a reference to the delegating class so this class can internally influence the TextField behavior as well.
|
||||||
|
private weak var proprietorTextDelegate: UITextFieldDelegate?
|
||||||
|
|
||||||
|
private var isEditting: Bool = false {
|
||||||
|
didSet {
|
||||||
|
viewModel.selected = isEditting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Stored Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private var observingForChange: Bool = false
|
||||||
|
|
||||||
|
/// Validate when user resigns editing. Default: true
|
||||||
|
open var validateWhenDoneEditing: Bool = true
|
||||||
|
|
||||||
|
open var shouldMaskWhileRecording: Bool {
|
||||||
|
return viewModel.shouldMaskRecordedView ?? false
|
||||||
|
}
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Computed Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
/// The text of this TextField.
|
||||||
|
open override var text: String? {
|
||||||
|
didSet {
|
||||||
|
viewModel?.text = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open override var errorText: String? {
|
||||||
|
get {
|
||||||
|
viewModel.dynamicErrorMessage ?? viewModel.errorMessage
|
||||||
|
}
|
||||||
|
set {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Placeholder access for the TextField.
|
||||||
|
public var placeholder: String? {
|
||||||
|
get { textField.placeholder }
|
||||||
|
set { textField.placeholder = newValue }
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Delegate Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// The delegate and block for validation. Validates if the text that the user has entered.
|
||||||
|
public weak var observingTextFieldDelegate: ObservingTextFieldDelegate?
|
||||||
|
|
||||||
|
/// If you're using a ViewController, you must set this to it
|
||||||
|
open weak var uiTextFieldDelegate: UITextFieldDelegate?
|
||||||
|
{
|
||||||
|
get { textField.delegate }
|
||||||
|
set {
|
||||||
|
textField.delegate = self
|
||||||
|
proprietorTextDelegate = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Lifecycle
|
||||||
|
//--------------------------------------------------
|
||||||
|
open override func setup() {
|
||||||
|
super.setup()
|
||||||
|
//turn off internal required rule
|
||||||
|
useRequiredRule = false
|
||||||
|
|
||||||
|
publisher(for: .valueChanged)
|
||||||
|
.sink { [weak self] control in
|
||||||
|
guard let self else { return }
|
||||||
|
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||||
|
if (viewModel.type == .email) {
|
||||||
|
// remove spaces (either user entered Or auto-correct suggestion) for the email field
|
||||||
|
text = textField.text?.replacingOccurrences(of: " ", with: "")
|
||||||
|
}
|
||||||
|
}.store(in: &subscribers)
|
||||||
|
|
||||||
|
textField
|
||||||
|
.publisher(for: .editingDidBegin)
|
||||||
|
.sink { [weak self] textView in
|
||||||
|
guard let self else { return }
|
||||||
|
isEditting = true
|
||||||
|
if viewModel.clearTextOnTap {
|
||||||
|
text = ""
|
||||||
|
}
|
||||||
|
}.store(in: &subscribers)
|
||||||
|
|
||||||
|
textField
|
||||||
|
.publisher(for: .editingDidEnd)
|
||||||
|
.sink { [weak self] textView in
|
||||||
|
guard let self else { return }
|
||||||
|
isEditting = false
|
||||||
|
if validateWhenDoneEditing, let valid = viewModel.isValid {
|
||||||
|
updateValidation(valid)
|
||||||
|
}
|
||||||
|
regexTextFieldOutputIfAvailable()
|
||||||
|
|
||||||
|
}.store(in: &subscribers)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@objc open func updateView(_ size: CGFloat) {}
|
||||||
|
|
||||||
|
@objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
|
||||||
|
observingTextFieldDelegate = delegate
|
||||||
|
uiTextFieldDelegate = delegate
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Observing for Change (TextFieldDelegate)
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
func regexTextFieldOutputIfAvailable() {
|
||||||
|
|
||||||
|
if let regex = viewModel?.displayFormat,
|
||||||
|
let mask = viewModel?.displayMask,
|
||||||
|
let finalText = text {
|
||||||
|
|
||||||
|
let range = NSRange(finalText.startIndex..., in: finalText)
|
||||||
|
|
||||||
|
if let regex = try? NSRegularExpression(pattern: regex) {
|
||||||
|
let maskedText = regex.stringByReplacingMatches(in: finalText,
|
||||||
|
range: range,
|
||||||
|
withTemplate: mask)
|
||||||
|
textField.text = maskedText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc public func dismissFieldInput(_ sender: Any?) {
|
||||||
|
_ = resignFirstResponder()
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - MoleculeViewProtocol
|
||||||
|
//--------------------------------------------------
|
||||||
|
open override func updateView() {
|
||||||
|
super.updateView()
|
||||||
|
|
||||||
|
if let viewModel {
|
||||||
|
switch viewModel.type {
|
||||||
|
case .secure:
|
||||||
|
textField.isSecureTextEntry = true
|
||||||
|
textField.shouldMaskWhileRecording = true
|
||||||
|
|
||||||
|
case .numberSecure:
|
||||||
|
textField.isSecureTextEntry = true
|
||||||
|
textField.shouldMaskWhileRecording = true
|
||||||
|
textField.keyboardType = .numberPad
|
||||||
|
|
||||||
|
case .email:
|
||||||
|
textField.keyboardType = .emailAddress
|
||||||
|
|
||||||
|
case .securityCode, .creditCard, .password:
|
||||||
|
textField.shouldMaskWhileRecording = true
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the preset keyboard set in type.
|
||||||
|
if let keyboardType = viewModel.assignKeyboardType() {
|
||||||
|
textField.keyboardType = keyboardType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
open func viewModelDidUpdate() {
|
||||||
|
|
||||||
|
fieldType = viewModel.type.toVDSFieldType()
|
||||||
|
text = viewModel.text
|
||||||
|
placeholder = viewModel.placeholder
|
||||||
|
|
||||||
|
labelText = viewModel.title
|
||||||
|
helperText = viewModel.feedback
|
||||||
|
isEnabled = viewModel.enabled
|
||||||
|
isReadOnly = viewModel.readOnly
|
||||||
|
isRequired = viewModel.required
|
||||||
|
tooltipModel = viewModel.tooltip?.toVDSTooltipModel()
|
||||||
|
width = viewModel.width
|
||||||
|
transparentBackground = viewModel.transparentBackground
|
||||||
|
|
||||||
|
containerView.accessibilityIdentifier = model.accessibilityIdentifier
|
||||||
|
textField.textAlignment = viewModel.textAlignment
|
||||||
|
textField.enableClipboardActions = viewModel.enableClipboardActions
|
||||||
|
textField.placeholder = viewModel.placeholder ?? ""
|
||||||
|
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
|
||||||
|
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
|
||||||
|
|
||||||
|
if (viewModel.selected ?? false) && !viewModel.wasInitiallySelected {
|
||||||
|
|
||||||
|
viewModel.wasInitiallySelected = true
|
||||||
|
isEditting = true
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.rules = rules
|
||||||
|
|
||||||
|
FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
|
||||||
|
|
||||||
|
if isEditting {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
_ = self.becomeFirstResponder()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.updateUI = {
|
||||||
|
MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
if isEditting {
|
||||||
|
updateValidation(viewModel.isValid ?? true)
|
||||||
|
|
||||||
|
} else if viewModel.isValid ?? true && showError {
|
||||||
|
showError = false
|
||||||
|
}
|
||||||
|
isEnabled = viewModel.enabled
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.updateUIDynamicError = {
|
||||||
|
MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
let validState = viewModel.isValid ?? false
|
||||||
|
if !validState && viewModel.shouldClearText {
|
||||||
|
text = ""
|
||||||
|
viewModel.shouldClearText = false
|
||||||
|
}
|
||||||
|
updateValidation(validState)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//Added to override text when view is reloaded.
|
||||||
|
if let text = viewModel.text, !text.isEmpty {
|
||||||
|
regexTextFieldOutputIfAvailable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateValidation(_ isValid: Bool) {
|
||||||
|
let previousValidity = self.isValid
|
||||||
|
self.isValid = isValid
|
||||||
|
|
||||||
|
if previousValidity && !isValid {
|
||||||
|
showError = true
|
||||||
|
//observingTextFieldDelegate?.isValid?(textfield: self)
|
||||||
|
} else if (!previousValidity && isValid) {
|
||||||
|
showError = false
|
||||||
|
//observingTextFieldDelegate?.isInvalid?(textfield: self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension InputEntryField {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Implemented TextField Delegate
|
||||||
|
//--------------------------------------------------
|
||||||
|
@discardableResult
|
||||||
|
@objc public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||||
|
proprietorTextDelegate?.textFieldShouldReturn?(textField) ?? true
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc public override func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||||
|
proprietorTextDelegate?.textField?(textField, shouldChangeCharactersIn: range, replacementString: string)
|
||||||
|
??
|
||||||
|
super.textField(textField, shouldChangeCharactersIn: range, replacementString: string)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc public override func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||||
|
proprietorTextDelegate?.textFieldDidBeginEditing?(textField) ?? super.textFieldDidBeginEditing(textField)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc public override func textFieldDidEndEditing(_ textField: UITextField) {
|
||||||
|
proprietorTextDelegate?.textFieldDidEndEditing?(textField) ?? super.textFieldDidEndEditing(textField)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
|
||||||
|
proprietorTextDelegate?.textFieldShouldBeginEditing?(textField) ?? true
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
|
||||||
|
proprietorTextDelegate?.textFieldShouldEndEditing?(textField) ?? true
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc public func textFieldShouldClear(_ textField: UITextField) -> Bool {
|
||||||
|
proprietorTextDelegate?.textFieldShouldClear?(textField) ?? true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Accessibility
|
||||||
|
extension InputEntryField {
|
||||||
|
|
||||||
|
@objc open func pushAccessibilityNotification() {
|
||||||
|
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
UIAccessibility.post(notification: .layoutChanged, argument: containerView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal struct ViewMasking {
|
||||||
|
static var shouldMaskWhileRecording: UInt8 = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
extension VDS.TextField: ViewMaskingProtocol {
|
||||||
|
public var shouldMaskWhileRecording: Bool {
|
||||||
|
get {
|
||||||
|
return (objc_getAssociatedObject(self, &ViewMasking.shouldMaskWhileRecording) as? Bool) ?? false
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
objc_setAssociatedObject(self, &ViewMasking.shouldMaskWhileRecording, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user