Skip to content

Commit 19ec851

Browse files
committed
Fixed delete backward issue
1 parent de826bf commit 19ec851

File tree

9 files changed

+311
-253
lines changed

9 files changed

+311
-253
lines changed

SwiftyCodeView.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
Pod::Spec.new do |s|
1010
s.swift_version = '4.1'
1111
s.name = 'SwiftyCodeView'
12-
s.version = '0.3.2'
12+
s.version = '0.3.3'
1313
s.summary = 'An UI Component for verification codes written in swift'
1414

1515
s.description = <<-DESC

SwiftyCodeView/Classes/SwiftyCodeView/SwiftyCodeTextField.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ open class SwiftyCodeTextField: UITextField {
1515
weak open var deleteDelegate: SwiftyCodeTextFieldDelegate?
1616

1717
override open func deleteBackward() {
18-
super.deleteBackward()
1918
deleteDelegate?.deleteBackward(sender: self)
19+
super.deleteBackward()
2020
}
2121
}

SwiftyCodeView/Classes/SwiftyCodeView/SwiftyCodeView.swift

Lines changed: 142 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -6,135 +6,155 @@
66

77
import UIKit
88

9+
#if canImport(RxCocoa)
10+
import RxSwift
11+
import RxCocoa
12+
extension Reactive where Base: SwiftyCodeView {
13+
14+
/// Reactive wrapper for `code` property.
15+
internal var code: ControlProperty<String> {
16+
return controlProperty(editingEvents: [.allEditingEvents, .valueChanged],
17+
getter: { codeView in
18+
codeView.code
19+
}, setter: { codeView, value in
20+
codeView.code = value
21+
})
22+
}
23+
}
24+
#endif
25+
26+
927
@objc
1028
public protocol SwiftyCodeViewDelegate: class {
11-
func codeView(sender: SwiftyCodeView, didFinishInput code: String)
29+
func codeView(sender: SwiftyCodeView, didFinishInput code: String)
1230
}
1331

1432
@IBDesignable
1533
open class SwiftyCodeView: UIControl {
16-
@IBInspectable open var length: Int = 4 {
17-
didSet {
18-
setupUI()
19-
}
20-
}
21-
22-
@IBOutlet open weak var delegate: SwiftyCodeViewDelegate?
23-
24-
var stackView: UIStackView = {
25-
let stackView = UIStackView()
26-
stackView.axis = .horizontal
27-
stackView.distribution = .equalSpacing
28-
stackView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
29-
return stackView
30-
}()
31-
32-
fileprivate var items: [SwiftyCodeItemView] = []
33-
open var code: String {
34-
get {
35-
let items = stackView.arrangedSubviews.map({$0 as! SwiftyCodeItemView})
36-
let values = items.map({$0.textField.text ?? ""})
37-
return values.joined()
38-
}
39-
set {
40-
let array = newValue.map(String.init)
41-
for i in 0..<array.count {
42-
let item = stackView.arrangedSubviews[i] as! SwiftyCodeItemView
43-
item.textField.text = array[i]
44-
}
45-
}
46-
}
47-
48-
override open func awakeFromNib() {
49-
super.awakeFromNib()
50-
setupUI()
51-
52-
let tap = UITapGestureRecognizer(target: self, action: #selector(becomeFirstResponder))
53-
addGestureRecognizer(tap)
54-
}
55-
56-
fileprivate func setupUI() {
57-
stackView.frame = self.bounds
58-
if stackView.superview == nil {
59-
addSubview(stackView)
60-
}
61-
stackView.arrangedSubviews.forEach{($0.removeFromSuperview())}
62-
63-
for i in 0..<length {
64-
let itemView = generateItem()
65-
itemView.textField.deleteDelegate = self
66-
itemView.textField.delegate = self
67-
itemView.tag = i
68-
itemView.textField.tag = i
69-
stackView.addArrangedSubview(itemView)
70-
}
71-
}
72-
73-
open func generateItem() -> SwiftyCodeItemView {
74-
let type = SwiftyCodeItemView.self
75-
let typeStr = type.description().components(separatedBy: ".").last ?? ""
76-
let bundle = Bundle(for: type)
77-
return bundle
78-
.loadNibNamed(typeStr,
79-
owner: nil,
80-
options: nil)?
81-
.last as! SwiftyCodeItemView
82-
}
83-
84-
override open func becomeFirstResponder() -> Bool {
85-
let items = stackView.arrangedSubviews
86-
.map({$0 as! SwiftyCodeItemView})
87-
return (items.filter({($0.textField.text ?? "").isEmpty}).first ?? items.last)!.becomeFirstResponder()
88-
}
89-
90-
override open func resignFirstResponder() -> Bool {
91-
stackView.arrangedSubviews.forEach({$0.resignFirstResponder()})
92-
return true
93-
}
94-
95-
override open func prepareForInterfaceBuilder() {
96-
super.prepareForInterfaceBuilder()
97-
setupUI()
98-
}
34+
@IBInspectable open var length: Int = 4 {
35+
didSet {
36+
setupUI()
37+
}
38+
}
39+
40+
@IBOutlet open weak var delegate: SwiftyCodeViewDelegate?
41+
42+
var stackView: UIStackView = {
43+
let stackView = UIStackView()
44+
stackView.axis = .horizontal
45+
stackView.distribution = .equalSpacing
46+
stackView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
47+
return stackView
48+
}()
49+
50+
fileprivate var items: [SwiftyCodeItemView] = []
51+
open var code: String {
52+
get {
53+
let items = stackView.arrangedSubviews.map({$0 as! SwiftyCodeItemView})
54+
let values = items.map({$0.textField.text ?? ""})
55+
return values.joined()
56+
}
57+
set {
58+
let array = newValue.map(String.init)
59+
for i in 0..<array.count {
60+
let item = stackView.arrangedSubviews[i] as! SwiftyCodeItemView
61+
item.textField.text = array[i]
62+
}
63+
}
64+
}
65+
66+
override open func awakeFromNib() {
67+
super.awakeFromNib()
68+
setupUI()
69+
70+
let tap = UITapGestureRecognizer(target: self, action: #selector(becomeFirstResponder))
71+
addGestureRecognizer(tap)
72+
}
73+
74+
fileprivate func setupUI() {
75+
stackView.frame = self.bounds
76+
if stackView.superview == nil {
77+
addSubview(stackView)
78+
}
79+
stackView.arrangedSubviews.forEach{($0.removeFromSuperview())}
80+
81+
for i in 0..<length {
82+
let itemView = generateItem()
83+
itemView.textField.deleteDelegate = self
84+
itemView.textField.delegate = self
85+
itemView.tag = i
86+
itemView.textField.tag = i
87+
stackView.addArrangedSubview(itemView)
88+
}
89+
}
90+
91+
open func generateItem() -> SwiftyCodeItemView {
92+
let type = SwiftyCodeItemView.self
93+
let typeStr = type.description().components(separatedBy: ".").last ?? ""
94+
let bundle = Bundle(for: type)
95+
return bundle
96+
.loadNibNamed(typeStr,
97+
owner: nil,
98+
options: nil)?
99+
.last as! SwiftyCodeItemView
100+
}
101+
102+
override open func becomeFirstResponder() -> Bool {
103+
let items = stackView.arrangedSubviews
104+
.map({$0 as! SwiftyCodeItemView})
105+
return (items.filter({($0.textField.text ?? "").isEmpty}).first ?? items.last)!.becomeFirstResponder()
106+
}
107+
108+
override open func resignFirstResponder() -> Bool {
109+
stackView.arrangedSubviews.forEach({$0.resignFirstResponder()})
110+
return true
111+
}
112+
113+
override open func prepareForInterfaceBuilder() {
114+
super.prepareForInterfaceBuilder()
115+
setupUI()
116+
}
99117
}
100118

101119
extension SwiftyCodeView: UITextFieldDelegate, SwiftyCodeTextFieldDelegate {
102-
103-
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
104-
105-
if string == "" { //is backspace
106-
return true
107-
}
108-
109-
if !textField.hasText {
110-
let index = textField.tag
111-
let item = stackView.arrangedSubviews[index] as! SwiftyCodeItemView
112-
item.textField.text = string
113-
sendActions(for: .valueChanged)
114-
if index == length - 1 { //is last textfield
115-
delegate?.codeView(sender: self, didFinishInput: self.code)
116-
textField.resignFirstResponder()
117-
return false
118-
}
119-
120-
_ = stackView.arrangedSubviews[index + 1].becomeFirstResponder()
121-
}
122-
123-
return false
124-
}
125-
126-
public func deleteBackward(sender: SwiftyCodeTextField) {
127-
for i in 1..<length{
128-
let itemView = stackView.arrangedSubviews[i] as! SwiftyCodeItemView
129-
130-
if !itemView.textField.isFirstResponder {
131-
continue
132-
}
133-
134-
let prevItem = stackView.arrangedSubviews[i-1] as! SwiftyCodeItemView
135-
_ = prevItem.becomeFirstResponder()
136-
prevItem.textField.text = ""
137-
}
138-
sendActions(for: .valueChanged)
139-
}
120+
121+
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
122+
123+
if string == "" { //is backspace
124+
return true
125+
}
126+
127+
if !textField.hasText {
128+
let index = textField.tag
129+
let item = stackView.arrangedSubviews[index] as! SwiftyCodeItemView
130+
item.textField.text = string
131+
sendActions(for: .valueChanged)
132+
if index == length - 1 { //is last textfield
133+
delegate?.codeView(sender: self, didFinishInput: self.code)
134+
textField.resignFirstResponder()
135+
return false
136+
}
137+
138+
_ = stackView.arrangedSubviews[index + 1].becomeFirstResponder()
139+
}
140+
141+
return false
142+
}
143+
144+
public func deleteBackward(sender: SwiftyCodeTextField) {
145+
for i in 1..<length{
146+
let itemView = stackView.arrangedSubviews[i] as! SwiftyCodeItemView
147+
148+
if !itemView.textField.isFirstResponder {
149+
continue
150+
}
151+
152+
let prevItem = stackView.arrangedSubviews[i-1] as! SwiftyCodeItemView
153+
if itemView.textField.text?.isEmpty ?? true {
154+
prevItem.textField.text = ""
155+
_ = prevItem.becomeFirstResponder()
156+
}
157+
}
158+
sendActions(for: .valueChanged)
159+
}
140160
}

SwiftyCodeViewDemo/Pods/SwiftyCodeView/SwiftyCodeView/Classes/SwiftyCodeTextField.swift

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SwiftyCodeViewDemo/Pods/SwiftyCodeView/SwiftyCodeView/Classes/SwiftyCodeView.swift

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>

SwiftyCodeViewDemoRX/Pods/SwiftyCodeView/SwiftyCodeView/Classes/SwiftyCodeView/SwiftyCodeTextField.swift

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)