Skip to content

Commit e4a4372

Browse files
author
Ahmet Sina Ustem
committed
Added DatePicker and ObjectPicker
1 parent a5047ed commit e4a4372

72 files changed

Lines changed: 6052 additions & 805 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ALFormInput.podspec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@ Pod::Spec.new do |s|
2323
s.dependency 'SkyFloatingLabelTextField', '~> 3.0'
2424
s.dependency 'PhoneNumberKit', '~> 3.1'
2525
s.dependency 'SwiftValidatorNew', '~> 4.2.0'
26+
s.dependency 'ActionSheetPicker-3.0'
27+
s.dependency 'AlExtensions'
2628
end
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//
2+
// ALDatePicker.swift
3+
// ALFormInput_Example
4+
//
5+
// Created by AppLogist on 14.04.2020.
6+
// Copyright © 2020 CocoaPods. All rights reserved.
7+
//
8+
9+
import SwiftValidatorNew
10+
import ActionSheetPicker_3_0
11+
import AlExtensions
12+
13+
public protocol ALDatePickerDelegate: class {
14+
func didSelectDate(_ view: ALDatePicker, selectedDate: Date)
15+
}
16+
17+
18+
public class ALDatePicker: ALValidatableTextField {
19+
20+
weak var datePickerDelegate: ALDatePickerDelegate?
21+
private var datePickerMode: UIDatePickerMode?
22+
private var minDate: Date?
23+
private var maxDate: Date?
24+
private var showFormat: String = "HH/mm/yyyy"
25+
private var locale: Locale?
26+
public var selectedDate: Date?
27+
28+
public override init(rules: [Rule], config: ALTextFieldConfig) {
29+
super.init(rules: rules, config: config)
30+
delegate = self
31+
}
32+
33+
public required init?(coder: NSCoder) {
34+
super.init(coder: coder)
35+
delegate = self
36+
}
37+
38+
public func setupPicker(pickerMode: UIDatePickerMode? = nil,
39+
minDate: Date? = nil,
40+
maxDate: Date? = nil,
41+
locale: Locale? = Locale.current,
42+
dateShowFormat: String = "HH/mm/yyyy") {
43+
self.datePickerMode = pickerMode
44+
self.minDate = minDate
45+
self.maxDate = maxDate
46+
self.locale = locale
47+
self.showFormat = dateShowFormat
48+
}
49+
50+
private func showActionSheetDatePicker() {
51+
let picker = ActionSheetDatePicker(title: title,
52+
datePickerMode: datePickerMode ?? UIDatePickerMode.date,
53+
selectedDate: selectedDate ?? Date(),
54+
doneBlock: { (_, selectedDate, _) in
55+
guard let selectedDate = selectedDate as? Date else { return }
56+
self.selectedDate = selectedDate
57+
self.text = selectedDate.formatted(format: self.showFormat)
58+
self.datePickerDelegate?.didSelectDate(self, selectedDate: selectedDate)
59+
},
60+
cancel: nil,
61+
origin: self)
62+
if let minDate = self.minDate {
63+
picker?.minimumDate = minDate
64+
}
65+
if let maxDate = self.maxDate {
66+
picker?.maximumDate = maxDate
67+
}
68+
if let locale = self.locale {
69+
picker?.locale = locale
70+
}
71+
picker?.addButtons()
72+
picker?.show()
73+
}
74+
75+
public override func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
76+
showActionSheetDatePicker()
77+
return false
78+
}
79+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//
2+
// ALStringPicker.swift
3+
// ALFormInput_Example
4+
//
5+
// Created by AppLogist on 14.04.2020.
6+
// Copyright © 2020 CocoaPods. All rights reserved.
7+
//
8+
9+
import SwiftValidatorNew
10+
import ActionSheetPicker_3_0
11+
import AlExtensions
12+
13+
public protocol ALPickable {
14+
var stringForShowingInPickerView: String? { get }
15+
}
16+
17+
public protocol ALObjectPickerDelegate: class {
18+
func didSelectObject(_ view: ALObjectPicker, selectedObject: ALPickable, selectedIndex: Int)
19+
}
20+
21+
22+
public class ALObjectPicker: ALValidatableTextField {
23+
24+
weak var objectPickerDelegate: ALObjectPickerDelegate?
25+
private var objects : [ALPickable]?
26+
private var selectedObject: ALPickable?
27+
28+
public override init(rules: [Rule], config: ALTextFieldConfig) {
29+
super.init(rules: rules, config: config)
30+
delegate = self
31+
}
32+
33+
public required init?(coder: NSCoder) {
34+
super.init(coder: coder)
35+
delegate = self
36+
}
37+
38+
public func setupPicker(objects: [ALPickable]? = nil, selectedObject: ALPickable? = nil) {
39+
self.objects = objects
40+
self.selectedObject = selectedObject
41+
if let selectedObject = selectedObject {
42+
text = selectedObject.stringForShowingInPickerView
43+
}
44+
}
45+
46+
private func showActionSheetStringPicker() {
47+
guard let objects = objects, !objects.isEmpty else {
48+
assertionFailure("Strings array must be set and must not be empty")
49+
return
50+
}
51+
/// - TODO: This is negotiable (What if picker view can contains same strings?)
52+
let initialSelection = Int(objects.firstIndex(where: { $0.stringForShowingInPickerView == selectedObject?.stringForShowingInPickerView }) ?? 0)
53+
let rows = objects.compactMap{ $0.stringForShowingInPickerView ?? ""}
54+
let picker = ActionSheetStringPicker(title: title,
55+
rows: rows,
56+
initialSelection: initialSelection,
57+
doneBlock: { [weak self] (_, selectedIndex, _) in
58+
guard let self = self else { return }
59+
let selectedObject = objects[selectedIndex]
60+
self.selectedObject = selectedObject
61+
self.text = selectedObject.stringForShowingInPickerView
62+
self.objectPickerDelegate?.didSelectObject(self,
63+
selectedObject: selectedObject,
64+
selectedIndex: selectedIndex)
65+
},
66+
cancel: nil,
67+
origin: self)
68+
picker?.addButtons()
69+
picker?.show()
70+
}
71+
72+
public override func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
73+
showActionSheetStringPicker()
74+
return false
75+
}
76+
}

ALFormInput/Classes/ALValidatableTextField.swift

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,17 @@ import UIKit
1010
import SkyFloatingLabelTextField
1111
import PhoneNumberKit
1212
import SwiftValidatorNew
13+
import ActionSheetPicker_3_0
1314

1415
public class ALValidatableTextField: SkyFloatingLabelTextField {
1516

1617
private let validator = Validator()
1718
private var config = ALTextFieldConfig()
1819
private var type = ALValidatableTextFieldType.optional
19-
20+
2021
private lazy var phoneNumberKit = PhoneNumberKit()
2122
private lazy var phoneFormatter = PartialFormatter()
2223

23-
// 3. And another stored property which will only be accessible in IB (because the "unavailable" attribute prevents its use in code)
24-
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'shape' instead.")
25-
@IBInspectable var textFieldType: String? {
26-
willSet {
27-
// Ensure user enters a valid shape while making it lowercase.
28-
// Ignore input if not valid.
29-
if let newShape = ALValidatableTextFieldType(rawValue: newValue?.lowercased() ?? "") {
30-
type = newShape
31-
}
32-
}
33-
didSet {
34-
setConfig(type)
35-
}
36-
}
3724

3825
// MARK: - Properties
3926
private var padding: UIEdgeInsets? {
@@ -93,6 +80,11 @@ public class ALValidatableTextField: SkyFloatingLabelTextField {
9380
if type == .creditCardNumber {
9481
addTarget(self, action: #selector(formatCreditCardString(_:)), for: .editingChanged)
9582
}
83+
84+
if type == .datePicker {
85+
delegate = self
86+
}
87+
9688
validator.registerField(self, rules: tmpRules)
9789
}
9890

@@ -243,8 +235,16 @@ public class ALValidatableTextField: SkyFloatingLabelTextField {
243235
self.padding = padding
244236
}
245237
}
246-
238+
// MARK: - UITextFieldDelegate
247239
extension ALValidatableTextField: UITextFieldDelegate {
240+
public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
241+
if type == .datePicker {
242+
243+
return false
244+
}
245+
return true
246+
}
247+
248248
public func textFieldDidEndEditing(_ textField: UITextField) {
249249
//
250250
}

ALFormInput/Classes/ALValidatableTextFieldType.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public enum ALValidatableTextFieldType: String {
1818
case tcIdentityNo = "tcIdentityNo"
1919
case passportNumber = "PassportNumber"
2020
case creditCardNumber = "CreditCardNumber"
21+
case datePicker = "DatePicker"
2122
case birthDate = "birthDate"
2223
case optional
2324

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//
2+
// AL+ActionSheetPicker.swift
3+
// ALFormInput_Example
4+
//
5+
// Created by AppLogist on 14.04.2020.
6+
// Copyright © 2020 CocoaPods. All rights reserved.
7+
//
8+
9+
import ActionSheetPicker_3_0
10+
11+
extension ActionSheetStringPicker {
12+
func addButtons() {
13+
/// - TODO: Titles should be localized
14+
let doneButton = UIBarButtonItem(title: "Tamam", style: .done, target: nil, action: nil)
15+
let cancelButton = UIBarButtonItem(title: "Vazgeç", style: .plain, target: nil, action: nil)
16+
setDoneButton(doneButton)
17+
setCancelButton(cancelButton)
18+
}
19+
}
20+
extension ActionSheetDatePicker {
21+
func addButtons() {
22+
/// - TODO: Titles should be localized
23+
let doneButton = UIBarButtonItem(title: "Tamam", style: .done, target: nil, action: nil)
24+
let cancelButton = UIBarButtonItem(title: "Vazgeç", style: .plain, target: nil, action: nil)
25+
setDoneButton(doneButton)
26+
setCancelButton(cancelButton)
27+
}
28+
}
29+
30+
extension ActionSheetMultipleStringPicker {
31+
func addButtons() {
32+
/// - TODO: Titles should be localized
33+
let doneButton = UIBarButtonItem(title: "Tamam", style: .done, target: nil, action: nil)
34+
let cancelButton = UIBarButtonItem(title: "Vazgeç", style: .plain, target: nil, action: nil)
35+
setDoneButton(doneButton)
36+
setCancelButton(cancelButton)
37+
}
38+
}

CODE_OF_CONDUCT.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
In the interest of fostering an open and welcoming environment, we as
6+
contributors and maintainers pledge to making participation in our project and
7+
our community a harassment-free experience for everyone, regardless of age, body
8+
size, disability, ethnicity, sex characteristics, gender identity and expression,
9+
level of experience, education, socio-economic status, nationality, personal
10+
appearance, race, religion, or sexual identity and orientation.
11+
12+
## Our Standards
13+
14+
Examples of behavior that contributes to creating a positive environment
15+
include:
16+
17+
* Using welcoming and inclusive language
18+
* Being respectful of differing viewpoints and experiences
19+
* Gracefully accepting constructive criticism
20+
* Focusing on what is best for the community
21+
* Showing empathy towards other community members
22+
23+
Examples of unacceptable behavior by participants include:
24+
25+
* The use of sexualized language or imagery and unwelcome sexual attention or
26+
advances
27+
* Trolling, insulting/derogatory comments, and personal or political attacks
28+
* Public or private harassment
29+
* Publishing others' private information, such as a physical or electronic
30+
address, without explicit permission
31+
* Other conduct which could reasonably be considered inappropriate in a
32+
professional setting
33+
34+
## Our Responsibilities
35+
36+
Project maintainers are responsible for clarifying the standards of acceptable
37+
behavior and are expected to take appropriate and fair corrective action in
38+
response to any instances of unacceptable behavior.
39+
40+
Project maintainers have the right and responsibility to remove, edit, or
41+
reject comments, commits, code, wiki edits, issues, and other contributions
42+
that are not aligned to this Code of Conduct, or to ban temporarily or
43+
permanently any contributor for other behaviors that they deem inappropriate,
44+
threatening, offensive, or harmful.
45+
46+
## Scope
47+
48+
This Code of Conduct applies both within project spaces and in public spaces
49+
when an individual is representing the project or its community. Examples of
50+
representing a project or community include using an official project e-mail
51+
address, posting via an official social media account, or acting as an appointed
52+
representative at an online or offline event. Representation of a project may be
53+
further defined and clarified by project maintainers.
54+
55+
## Enforcement
56+
57+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
58+
reported by contacting the project team at info@applogist.com. All
59+
complaints will be reviewed and investigated and will result in a response that
60+
is deemed necessary and appropriate to the circumstances. The project team is
61+
obligated to maintain confidentiality with regard to the reporter of an incident.
62+
Further details of specific enforcement policies may be posted separately.
63+
64+
Project maintainers who do not follow or enforce the Code of Conduct in good
65+
faith may face temporary or permanent repercussions as determined by other
66+
members of the project's leadership.
67+
68+
## Attribution
69+
70+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71+
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72+
73+
[homepage]: https://www.contributor-covenant.org
74+
75+
For answers to common questions about this code of conduct, see
76+
https://www.contributor-covenant.org/faq

0 commit comments

Comments
 (0)