Skip to content

Commit 7d356bf

Browse files
committed
Finish implementing out-of-the-box fields
1 parent ef1b560 commit 7d356bf

File tree

7 files changed

+120
-74
lines changed

7 files changed

+120
-74
lines changed

CodeInputView.xcodeproj/project.pbxproj

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
CE901F20205AF28000C688DD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE901F1F205AF28000C688DD /* Assets.xcassets */; };
1414
CE901F23205AF28000C688DD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE901F21205AF28000C688DD /* LaunchScreen.storyboard */; };
1515
CE901F2B205AF32600C688DD /* CodeInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE901F2A205AF32600C688DD /* CodeInputView.swift */; };
16-
CEBF4F4B2066881500D31600 /* CodeInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBF4F4A2066881500D31600 /* CodeInputField.swift */; };
16+
CEBF4F4B2066881500D31600 /* LabelBasedInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBF4F4A2066881500D31600 /* LabelBasedInputField.swift */; };
1717
CEBF4F4D2066A2AD00D31600 /* DotInputField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBF4F4C2066A2AD00D31600 /* DotInputField.swift */; };
18+
CEBF4F4F2066EFEC00D31600 /* InputableField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBF4F4E2066EFEC00D31600 /* InputableField.swift */; };
1819
/* End PBXBuildFile section */
1920

2021
/* Begin PBXFileReference section */
@@ -26,8 +27,9 @@
2627
CE901F22205AF28000C688DD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
2728
CE901F24205AF28000C688DD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
2829
CE901F2A205AF32600C688DD /* CodeInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeInputView.swift; sourceTree = "<group>"; };
29-
CEBF4F4A2066881500D31600 /* CodeInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeInputField.swift; sourceTree = "<group>"; };
30+
CEBF4F4A2066881500D31600 /* LabelBasedInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelBasedInputField.swift; sourceTree = "<group>"; };
3031
CEBF4F4C2066A2AD00D31600 /* DotInputField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotInputField.swift; sourceTree = "<group>"; };
32+
CEBF4F4E2066EFEC00D31600 /* InputableField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputableField.swift; sourceTree = "<group>"; };
3133
/* End PBXFileReference section */
3234

3335
/* Begin PBXFrameworksBuildPhase section */
@@ -67,8 +69,9 @@
6769
CE901F21205AF28000C688DD /* LaunchScreen.storyboard */,
6870
CE901F24205AF28000C688DD /* Info.plist */,
6971
CE901F2A205AF32600C688DD /* CodeInputView.swift */,
70-
CEBF4F4A2066881500D31600 /* CodeInputField.swift */,
72+
CEBF4F4A2066881500D31600 /* LabelBasedInputField.swift */,
7173
CEBF4F4C2066A2AD00D31600 /* DotInputField.swift */,
74+
CEBF4F4E2066EFEC00D31600 /* InputableField.swift */,
7275
);
7376
path = CodeInputView;
7477
sourceTree = "<group>";
@@ -148,8 +151,9 @@
148151
CE901F2B205AF32600C688DD /* CodeInputView.swift in Sources */,
149152
CEBF4F4D2066A2AD00D31600 /* DotInputField.swift in Sources */,
150153
CE901F1B205AF28000C688DD /* ViewController.swift in Sources */,
151-
CEBF4F4B2066881500D31600 /* CodeInputField.swift in Sources */,
154+
CEBF4F4B2066881500D31600 /* LabelBasedInputField.swift in Sources */,
152155
CE901F19205AF28000C688DD /* AppDelegate.swift in Sources */,
156+
CEBF4F4F2066EFEC00D31600 /* InputableField.swift in Sources */,
153157
);
154158
runOnlyForDeploymentPostprocessing = 0;
155159
};

CodeInputView/CodeInputField.swift

Lines changed: 0 additions & 46 deletions
This file was deleted.

CodeInputView/CodeInputView.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,7 @@
99
import Foundation
1010
import UIKit
1111

12-
protocol InputableField {
13-
func deleteValue()
14-
func setValue(_ newValue: String)
15-
func getValue() -> String
16-
func isEmpty() -> Bool
17-
}
18-
19-
class CodeInputView<T: InputableField&UIView>: UIView, UIKeyInput {
12+
class CodeInputView<T: InputableField>: UIView, UIKeyInput {
2013
private var fields = [T]()
2114
private var currentIndex = 0
2215
var numberOfFields = 4 {
@@ -41,6 +34,8 @@ class CodeInputView<T: InputableField&UIView>: UIView, UIKeyInput {
4134

4235
var keyboardType: UIKeyboardType = .numberPad
4336

37+
var onCodeDidEnter: ((String) -> ())?
38+
4439
private var sizeOfField: CGFloat {
4540
let frameWidth = frame.width
4641
let minBySides = min(frameWidth - horizontalMargins * 2, frame.height * 0.8)
@@ -114,6 +109,12 @@ class CodeInputView<T: InputableField&UIView>: UIView, UIKeyInput {
114109
})
115110
}
116111

112+
func clear() {
113+
fields.forEach({ $0.deleteValue() })
114+
updateCode()
115+
currentIndex = 0
116+
}
117+
117118
func insertText(_ text: String) {
118119
guard currentIndex < fields.count else {
119120
return
@@ -136,6 +137,9 @@ class CodeInputView<T: InputableField&UIView>: UIView, UIKeyInput {
136137

137138
private func updateCode() {
138139
code = fields.reduce("", { $0 + $1.getValue() })
140+
if code.count == numberOfFields {
141+
onCodeDidEnter?(code)
142+
}
139143
}
140144
}
141145

CodeInputView/DotInputField.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class DotInputField: UIView, InputableField {
1919

2020
private var value: String?
2121
static var configuration: Configuration = Configuration()
22-
22+
2323
var dotRect: CGRect {
2424
let size = DotInputField.configuration.dotSize
2525
return CGRect(x: (bounds.width - size) * 0.5,

CodeInputView/InputableField.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// InputableField.swift
3+
// CodeInputView
4+
//
5+
// Created by Isa Aliev on 24.03.18.
6+
// Copyright © 2018 IA. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import UIKit
11+
12+
protocol InputableField where Self: UIView {
13+
func deleteValue()
14+
func setValue(_ newValue: String)
15+
func getValue() -> String
16+
func isEmpty() -> Bool
17+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//
2+
// LabelBasedInputField.swift
3+
// CodeInputView
4+
//
5+
// Created by Isa Aliev on 24.03.18.
6+
// Copyright © 2018 IA. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import UIKit
11+
12+
class LabelBasedInputField: UILabel, InputableField {
13+
struct Configuration {
14+
typealias AppearanceBlock = (UILabel) -> ()
15+
16+
var onLayoutAppearanceBlock: AppearanceBlock?
17+
var initialAppearanceBlock: AppearanceBlock?
18+
var emptyAppearanceBlock: AppearanceBlock?
19+
var filledAppearanceBlock: AppearanceBlock?
20+
}
21+
22+
23+
private var value: String?
24+
25+
static var configuration: LabelBasedInputField.Configuration? = LabelBasedInputField.Configuration()
26+
27+
override init(frame: CGRect) {
28+
super.init(frame: frame)
29+
30+
LabelBasedInputField.configuration?.initialAppearanceBlock?(self)
31+
}
32+
33+
required init?(coder aDecoder: NSCoder) {
34+
super.init(coder: aDecoder)
35+
}
36+
37+
override func layoutSubviews() {
38+
super.layoutSubviews()
39+
40+
LabelBasedInputField.configuration?.onLayoutAppearanceBlock?(self)
41+
}
42+
43+
func deleteValue() {
44+
LabelBasedInputField.configuration?.initialAppearanceBlock?(self)
45+
LabelBasedInputField.configuration?.emptyAppearanceBlock?(self)
46+
value = ""
47+
text = nil
48+
}
49+
50+
func setValue(_ newValue: String) {
51+
LabelBasedInputField.configuration?.initialAppearanceBlock?(self)
52+
LabelBasedInputField.configuration?.filledAppearanceBlock?(self)
53+
value = newValue
54+
text = newValue
55+
}
56+
57+
func getValue() -> String {
58+
return value ?? ""
59+
}
60+
61+
func isEmpty() -> Bool {
62+
return value == nil
63+
}
64+
}

CodeInputView/ViewController.swift

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,33 @@
99
import UIKit
1010

1111
class ViewController: UIViewController {
12-
1312
override func viewDidLoad() {
1413
super.viewDidLoad()
1514

16-
CodeInputField.configuration.emptyStateBlock = { label in
17-
label.backgroundColor = .gray
18-
label.layer.cornerRadius = label.bounds.height / 2.0
19-
label.layer.masksToBounds = true
20-
label.textAlignment = .center
15+
LabelBasedInputField.configuration?.initialAppearanceBlock = { field in
16+
field.textAlignment = .center
17+
field.backgroundColor = .white
18+
field.textColor = .black
19+
field.font = UIFont.systemFont(ofSize: 17.0, weight: .bold)
2120
}
2221

23-
CodeInputField.configuration.filledStateBlock = { label in
24-
label.backgroundColor = .white
22+
LabelBasedInputField.configuration?.onLayoutAppearanceBlock = { field in
23+
field.layer.cornerRadius = field.bounds.height / 2
24+
field.layer.masksToBounds = true
25+
field.layer.borderWidth = 1.0
26+
field.layer.borderColor = UIColor.black.cgColor
2527
}
2628

27-
28-
DotInputField.configuration.fillColor = .cyan
29-
let c = CodeInputView<CodeInputField>()
30-
c.frame = CGRect(x: 16.0, y: 200.0, width: 250.0, height: 100.0)
31-
c.backgroundColor = .green
29+
let c = CodeInputView<LabelBasedInputField>()
30+
c.numberOfFields = 10
31+
c.frame = CGRect(x: 0.0, y: 200.0, width: 375.0, height: 100.0)
3232
view.addSubview(c)
3333
c.becomeFirstResponder()
34-
35-
// Do any additional setup after loading the view, typically from a nib.
34+
35+
c.onCodeDidEnter = { code in
36+
print(code)
37+
c.clear()
38+
}
3639
}
3740
}
3841

0 commit comments

Comments
 (0)