HideShowPasswordTextFieldDelegate.swift 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. //
  2. // HideShowPasswordTextFieldDelegate.swift
  3. // CockFight
  4. //
  5. // Created by Visoth Phon on 3/20/21.
  6. //
  7. import Foundation
  8. import UIKit
  9. protocol HideShowPasswordTextFieldDelegate: class {
  10. func isValidPassword(_ password: String) -> Bool
  11. }
  12. public class HideShowPasswordTextField: UITextField {
  13. weak var passwordDelegate: HideShowPasswordTextFieldDelegate?
  14. var preferredFont: UIFont? {
  15. didSet {
  16. self.font = nil
  17. if self.isSecureTextEntry {
  18. self.font = self.preferredFont
  19. }
  20. }
  21. }
  22. override public var isSecureTextEntry: Bool {
  23. didSet {
  24. if !self.isSecureTextEntry {
  25. self.font = nil
  26. self.font = self.preferredFont
  27. }
  28. // Hack to prevent text from getting cleared when switching secure entry
  29. if self.isFirstResponder {
  30. _ = self.becomeFirstResponder()
  31. }
  32. }
  33. }
  34. fileprivate var passwordToggleVisibilityView: PasswordToggleVisibilityView!
  35. override init(frame: CGRect) {
  36. super.init(frame: frame)
  37. setupViews()
  38. }
  39. required init?(coder aDecoder: NSCoder) {
  40. super.init(coder: aDecoder)
  41. }
  42. override public func awakeFromNib() {
  43. super.awakeFromNib()
  44. setupViews()
  45. }
  46. override public func becomeFirstResponder() -> Bool {
  47. // Hack to prevent text from getting cleared when switching secure entry
  48. // https://stackoverflow.com/a/49771445/1417922
  49. let success = super.becomeFirstResponder()
  50. if self.isSecureTextEntry, let text = self.text {
  51. self.text?.removeAll()
  52. self.insertText(text)
  53. }
  54. return success
  55. }
  56. }
  57. // MARK: UITextFieldDelegate needed calls
  58. // Implement UITextFieldDelegate when you use this, and forward these calls to this class!
  59. extension HideShowPasswordTextField {
  60. func textFieldDidEndEditing(_ textField: UITextField) {
  61. passwordToggleVisibilityView.eyeState = PasswordToggleVisibilityView.EyeState.closed
  62. self.isSecureTextEntry = !isSelected
  63. }
  64. }
  65. // MARK: PasswordToggleVisibilityDelegate
  66. extension HideShowPasswordTextField: PasswordToggleVisibilityDelegate {
  67. func viewWasToggled(_ passwordToggleVisibilityView: PasswordToggleVisibilityView, isSelected selected: Bool) {
  68. // hack to fix a bug with padding when switching between secureTextEntry state
  69. let hackString = self.text
  70. self.text = " "
  71. self.text = hackString
  72. // hack to save our correct font. The order here is VERY finicky
  73. self.isSecureTextEntry = !selected
  74. }
  75. }
  76. // MARK: Control events
  77. extension HideShowPasswordTextField {
  78. }
  79. // MARK: Private helpers
  80. extension HideShowPasswordTextField {
  81. fileprivate func setupViews() {
  82. let toggleFrame = CGRect(x: 0, y: 0, width: 66, height: frame.height)
  83. passwordToggleVisibilityView = PasswordToggleVisibilityView(frame: toggleFrame)
  84. passwordToggleVisibilityView.delegate = self
  85. self.keyboardType = .asciiCapable
  86. self.rightView = passwordToggleVisibilityView
  87. self.font = self.preferredFont
  88. // if we don't do this, the eye flies in on textfield focus!
  89. self.rightView?.frame = self.rightViewRect(forBounds: self.bounds)
  90. self.rightViewMode = .whileEditing
  91. // left view hack to add padding
  92. self.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 3))
  93. self.leftViewMode = .always
  94. }
  95. }