You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.8 KiB

  1. //
  2. // CreditCardView.swift
  3. // GME Remit
  4. //
  5. // Created by InKwon James Kim on 2019/10/15.
  6. // Copyright © 2019 Gobal Money Express Co. Ltd. All rights reserved.
  7. //
  8. import UIKit
  9. @IBDesignable
  10. class CreditCardView: UIView {
  11. private enum PickerType: Int {
  12. case month = 0
  13. case year
  14. }
  15. private let xibName = "CreditCardView"
  16. @IBOutlet private weak var firstNumberTextField: UITextField!
  17. @IBOutlet private weak var secondNumberTextField: UITextField!
  18. @IBOutlet private weak var thirdNumberTextField: UITextField!
  19. @IBOutlet private weak var fourthNumberTextField: UITextField!
  20. @IBOutlet private weak var monthTextField: UITextField!
  21. @IBOutlet private weak var yearTextField: UITextField!
  22. @IBOutlet private weak var cardCompanyImageView: UIImageView!
  23. private var textFields: [UITextField]?
  24. private var months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10" ,"11", "12"]
  25. private var years = [String]()
  26. override init(frame: CGRect) {
  27. super.init(frame: frame)
  28. commonInit()
  29. }
  30. required init?(coder: NSCoder) {
  31. super.init(coder: coder)
  32. commonInit()
  33. }
  34. private func commonInit() {
  35. guard let view = Bundle.main.loadNibNamed(
  36. xibName,
  37. owner: self,
  38. options: nil
  39. )?.first as? UIView else { return }
  40. view.frame = self.bounds
  41. view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  42. view.layer.cornerRadius = 10
  43. self.addSubview(view)
  44. textFields = [
  45. firstNumberTextField, secondNumberTextField, thirdNumberTextField, fourthNumberTextField,
  46. monthTextField, yearTextField
  47. ]
  48. textFields?.forEach {
  49. $0.addTarget(self, action: #selector(editingDidBegin(_:)), for: .editingDidBegin)
  50. $0.addTarget(self, action: #selector(editingChanged(_:)), for: .editingChanged)
  51. }
  52. let monthPickerView = UIPickerView()
  53. monthPickerView.tag = 0
  54. monthPickerView.delegate = self
  55. monthPickerView.dataSource = self
  56. monthTextField.inputView = monthPickerView
  57. let yearPickerView = UIPickerView()
  58. yearPickerView.tag = 1
  59. yearPickerView.delegate = self
  60. yearPickerView.dataSource = self
  61. yearTextField.inputView = yearPickerView
  62. let format = DateFormatter()
  63. format.dateFormat = "yy"
  64. let now = Date()
  65. let min = Int(format.string(from: now)) ?? 19
  66. let max = min + 5
  67. for year in min...max {
  68. years.append("\(year)")
  69. }
  70. }
  71. func focusFirstNumberField() {
  72. firstNumberTextField.becomeFirstResponder()
  73. }
  74. @objc private func editingChanged(_ textField: UITextField) {
  75. let limitCount: Int
  76. switch textField {
  77. case monthTextField, yearTextField:
  78. limitCount = 2
  79. default:
  80. limitCount = 4
  81. }
  82. if textField.text?.count == limitCount,
  83. let index = textFields?.firstIndex(of: textField)?.advanced(by: 1) {
  84. if index < textFields?.count ?? 6, textFields?[index].text?.count != limitCount {
  85. textFields?[index].becomeFirstResponder()
  86. } else {
  87. textField.resignFirstResponder()
  88. guard
  89. let first = firstNumberTextField.text,
  90. let second = secondNumberTextField.text,
  91. let third = thirdNumberTextField.text,
  92. let fourth = fourthNumberTextField.text,
  93. let month = monthTextField.text,
  94. let year = yearTextField.text else {
  95. return
  96. }
  97. let cardNumber = first + second + third + fourth
  98. cardCompanyImageView.image = CreditCardType.validate(cardNumber: cardNumber)?.image
  99. }
  100. }
  101. }
  102. @objc private func editingDidBegin(_ textField: UITextField) {
  103. textField.text = nil
  104. }
  105. }
  106. extension CreditCardView: UIPickerViewDataSource {
  107. func numberOfComponents(in pickerView: UIPickerView) -> Int {
  108. return 1
  109. }
  110. func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
  111. guard let type = PickerType(rawValue: pickerView.tag) else { return 0 }
  112. switch type {
  113. case .month: return months.count
  114. case .year: return years.count
  115. }
  116. }
  117. func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
  118. guard let type = PickerType(rawValue: pickerView.tag) else { return nil }
  119. switch type {
  120. case .month: return months[row]
  121. case .year: return years[row]
  122. }
  123. }
  124. }
  125. extension CreditCardView: UIPickerViewDelegate {
  126. func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
  127. guard let type = PickerType(rawValue: pickerView.tag) else { return }
  128. switch type {
  129. case .month:
  130. monthTextField.text = months[row]
  131. monthTextField.sendActions(for: .editingChanged)
  132. case .year:
  133. yearTextField.text = years[row]
  134. yearTextField.sendActions(for: .editingChanged)
  135. }
  136. }
  137. }