Skip to content

Commit 60e836d

Browse files
committed
added dropdownx
1 parent b9475b5 commit 60e836d

File tree

5 files changed

+323
-3
lines changed

5 files changed

+323
-3
lines changed

iOSFormUtils.podspec

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
Pod::Spec.new do |s|
1010
s.name = "iOSFormUtils"
11-
s.version = "0.3.0"
11+
s.version = "0.3.1"
1212
s.summary = "iOSFormUtils helps you developping validated forms in iOS apps."
1313

1414
# This description is used to generate tags and improve search results.
@@ -30,5 +30,7 @@ iOSFormUtils helps you developping validated forms in iOS apps. You could use it
3030
s.ios.deployment_target = '8.0'
3131

3232
s.source_files = 'iOSFormUtils'
33-
33+
34+
s.dependency 'SBPickerSelector', '~> 1.1.0'
35+
s.dependency 'UIKitExtensions', '~> 0.2.4'
3436
end

iOSFormUtils/DateDropDown.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// DateDropDown.swift
3+
// application
4+
//
5+
// Created by Nicolas LELOUP on 25/02/2017.
6+
// Copyright © 2017 Nicolas LELOUP - Buzznative. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import UIKit
11+
12+
protocol DateDropDownDelegate {
13+
func dropDown(_ dropDown: DateDropDown!, selectedDate value: Date!)
14+
}
15+
16+
public class DateDropDown: DropDown {
17+
var selectedDate: Date! {
18+
didSet {
19+
if selectedDate != oldValue {
20+
self.refreshDateView()
21+
}
22+
}
23+
}
24+
var dateDropDownDelegate: DateDropDownDelegate!
25+
26+
func refreshDateView() {
27+
let dateFormatter = DateFormatter()
28+
dateFormatter.dateFormat = self.dateFormat
29+
30+
titleTextField.text = dateFormatter.string(from: selectedDate)
31+
if let _ = self.dataSource {
32+
titleTextField.textColor = self.dataSource.getTextColor()
33+
titleTextField.font = UIFont(name: self.dataSource.getFontName(), size: self.dataSource.getFontSize())
34+
}
35+
}
36+
37+
override public func loadView() {
38+
super.loadView()
39+
40+
picker.pickerType = .date
41+
picker.onlyDayPicker = true
42+
picker.datePickerType = .onlyDay
43+
}
44+
}

iOSFormUtils/DropDown.swift

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
//
2+
// DropDown.swift
3+
// application
4+
//
5+
// Created by Nicolas LELOUP on 25/02/2017.
6+
// Copyright © 2017 Nicolas LELOUP - Buzznative. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import SBPickerSelector
11+
import UIKit
12+
import UIKitExtensions
13+
14+
protocol DropDownDataSource {
15+
func controllerForDropDownDisplaying(_ dropDown: DropDown) -> UIViewController
16+
17+
func valuesForDropDown(_ dropDown: DropDown) -> [String]
18+
19+
func selectedIndexForDropDown(_ dropDown: DropDown) -> Int?
20+
21+
func placeholderKeyForDropDown(_ dropDown: DropDown) -> String?
22+
23+
func isRequired(_ dropDown: DropDown) -> Bool
24+
25+
func getTextColor() -> UIColor
26+
27+
func getFontName() -> String
28+
29+
func getFontSize() -> CGFloat
30+
31+
func getRightIcon() -> UIImage
32+
}
33+
34+
protocol DropDownDelegate {
35+
func dropDown(_ dropDown: DropDown!, selectedValue value: String!, index: Int)
36+
37+
func dropDownDeselectedValue(_ dropDown: DropDown!)
38+
}
39+
40+
public class DropDown: OwnView {
41+
var dateFormat = "dd/MM/y"
42+
43+
var delegate: DropDownDelegate!
44+
var dataSource: DropDownDataSource! {
45+
didSet {
46+
updatePlaceholder()
47+
}
48+
}
49+
50+
var picker: SBPickerSelector = SBPickerSelector.picker()
51+
var values: [String]!
52+
var currentTextField: FormInput!
53+
var selectedIndex: Int!
54+
55+
var mainColor: UIColor = UIColor.blue
56+
57+
@IBOutlet weak var rightIcon: UIImageView!
58+
@IBOutlet weak var titleTextField: FormInput!
59+
60+
override public func loadView() {
61+
super.loadView()
62+
63+
picker.delegate = self
64+
picker.pickerType = SBPickerSelectorType.text
65+
picker.doneButtonTitle = "OK"
66+
picker.doneButton?.tintColor = mainColor
67+
picker.cancelButtonTitle = "Annuler"
68+
picker.cancelButton?.tintColor = mainColor
69+
70+
updatePlaceholder()
71+
72+
reloadData()
73+
74+
NotificationCenter.default.addObserver(
75+
self,
76+
selector: #selector(DropDown.textFieldBecameFirstResponder(_:)),
77+
name: NSNotification.Name(rawValue: "textFieldBecameFirstResponder"),
78+
object: nil
79+
)
80+
}
81+
82+
func updatePlaceholder() {
83+
if let _ = dataSource {
84+
if let existingPlaceholder = dataSource.placeholderKeyForDropDown(self) {
85+
updatePlaceholderWithValue(existingPlaceholder)
86+
}
87+
}
88+
}
89+
90+
func updatePlaceholderWithValue(_ value: String) {
91+
titleTextField.attributedPlaceholder = NSAttributedString(
92+
string: value,
93+
attributes: [
94+
NSForegroundColorAttributeName: self.dataSource.getTextColor(),
95+
NSFontAttributeName: UIFont(name: self.dataSource.getFontName(), size: self.dataSource.getFontSize())!
96+
]
97+
)
98+
}
99+
100+
func updateSelectedIndex(_ newIndex: Int) {
101+
selectedIndex = newIndex
102+
picker.pickerView.selectRow(selectedIndex, inComponent: 0, animated: true)
103+
if let data: [String] = picker.pickerData as? [String] {
104+
pickerSelector(picker, selectedValue: data[selectedIndex], index: selectedIndex)
105+
picker.pickerView(picker.pickerView, didSelectRow: selectedIndex, inComponent: 0)
106+
}
107+
}
108+
109+
func resetValue() {
110+
titleTextField.text! = ""
111+
}
112+
113+
func reloadData() {
114+
updatePlaceholder()
115+
if let itsDataSource = dataSource {
116+
var values: [String] = itsDataSource.valuesForDropDown(self)
117+
var offset = 0
118+
if nil != dataSource && !dataSource.isRequired(self) {
119+
values.insert("-", at: 0)
120+
offset = 1
121+
}
122+
123+
picker.pickerData = values
124+
if let dataSourceSelectedIndex: Int = itsDataSource.selectedIndexForDropDown(self) {
125+
updateSelectedIndex(dataSourceSelectedIndex + offset)
126+
}
127+
}
128+
}
129+
130+
func presentDropDown() {
131+
if let itsDataSource = dataSource {
132+
if let textField = currentTextField {
133+
textField.resignFirstResponder()
134+
}
135+
picker.showPickerOver(itsDataSource.controllerForDropDownDisplaying(self))
136+
}
137+
}
138+
139+
@IBAction func mainButtonTouched(_ sender: AnyObject) {
140+
presentDropDown()
141+
}
142+
143+
func textFieldBecameFirstResponder(_ notification: Notification) {
144+
if let textField: FormInput = notification.object as? FormInput {
145+
if textField != titleTextField {
146+
currentTextField = textField
147+
} else {
148+
currentTextField = nil
149+
}
150+
}
151+
}
152+
}
153+
154+
extension DropDown: OwnViewProtocol {
155+
public var viewName: String {
156+
return "DropDown"
157+
}
158+
}
159+
160+
extension DropDown: SBPickerSelectorDelegate {
161+
public func pickerSelector(_ selector: SBPickerSelector!, selectedValue value: String!, index idx: Int) {
162+
let required = (nil != dataSource && !dataSource.isRequired(self))
163+
var offset = 0
164+
if (required && 0 != idx) || !required {
165+
titleTextField.text = value
166+
titleTextField.textColor = self.dataSource.getTextColor()
167+
titleTextField.font = UIFont(name: self.dataSource.getFontName(), size: self.dataSource.getFontSize())
168+
if required {
169+
offset = 1
170+
}
171+
172+
if let itsDelegate = delegate {
173+
itsDelegate.dropDown(self, selectedValue: value, index: idx - offset)
174+
self.selectedIndex = idx - offset
175+
}
176+
} else {
177+
resetValue()
178+
179+
if let itsDelegate = delegate {
180+
itsDelegate.dropDownDeselectedValue(self)
181+
self.selectedIndex = nil
182+
}
183+
}
184+
}
185+
186+
public func pickerSelector(_ selector: SBPickerSelector!, dateSelected date: Date!) {
187+
if .date == picker.pickerType {
188+
if let _ = date {
189+
let dateFormatter = DateFormatter()
190+
dateFormatter.dateFormat = self.dateFormat
191+
192+
titleTextField.text = dateFormatter.string(from: date)
193+
titleTextField.textColor = self.dataSource.getTextColor()
194+
titleTextField.font = UIFont(name: self.dataSource.getFontName(), size: self.dataSource.getFontSize())
195+
196+
if let dateSelf: DateDropDown = self as? DateDropDown {
197+
if let dateDropDownDelegate: DateDropDownDelegate = dateSelf.dateDropDownDelegate {
198+
dateDropDownDelegate.dropDown(dateSelf, selectedDate: date)
199+
dateSelf.selectedDate = date
200+
}
201+
}
202+
}
203+
}
204+
}
205+
}

iOSFormUtils/DropDown.xib

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
3+
<device id="retina4_7" orientation="portrait">
4+
<adaptation id="fullscreen"/>
5+
</device>
6+
<dependencies>
7+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
8+
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
9+
</dependencies>
10+
<customFonts key="customFonts">
11+
<array key="HalisR-Bold.otf">
12+
<string>HalisR-Bold</string>
13+
</array>
14+
</customFonts>
15+
<objects>
16+
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="Selector" customModule="application" customModuleProvider="target">
17+
<connections>
18+
<outlet property="rightIcon" destination="Z4l-DI-rS9" id="fpW-WP-AzI"/>
19+
<outlet property="titleTextField" destination="NNd-8B-dbM" id="JII-ZE-r6a"/>
20+
</connections>
21+
</placeholder>
22+
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
23+
<view contentMode="scaleToFill" id="iN0-l3-epB">
24+
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
25+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
26+
<subviews>
27+
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="NNd-8B-dbM" customClass="BaseTextField" customModule="application" customModuleProvider="target">
28+
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
29+
<fontDescription key="fontDescription" name="HalisR-Bold" family="Halis R" pointSize="17"/>
30+
<textInputTraits key="textInputTraits"/>
31+
</textField>
32+
<imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SelectorIcon" translatesAutoresizingMaskIntoConstraints="NO" id="Z4l-DI-rS9">
33+
<rect key="frame" x="355" y="0.0" width="20" height="667"/>
34+
<constraints>
35+
<constraint firstAttribute="width" constant="20" id="3XV-Yu-Jnc"/>
36+
</constraints>
37+
</imageView>
38+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a2q-wM-NML">
39+
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
40+
<connections>
41+
<action selector="mainButtonTouched:" destination="-1" eventType="touchUpInside" id="SX1-u8-7yY"/>
42+
</connections>
43+
</button>
44+
</subviews>
45+
<constraints>
46+
<constraint firstItem="a2q-wM-NML" firstAttribute="height" secondItem="iN0-l3-epB" secondAttribute="height" id="2Af-tS-O9c"/>
47+
<constraint firstAttribute="trailing" secondItem="Z4l-DI-rS9" secondAttribute="trailing" id="Eva-FJ-UiY"/>
48+
<constraint firstItem="NNd-8B-dbM" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="Gve-YT-IYZ"/>
49+
<constraint firstItem="a2q-wM-NML" firstAttribute="width" secondItem="iN0-l3-epB" secondAttribute="width" id="KSj-CL-X1R"/>
50+
<constraint firstItem="NNd-8B-dbM" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="RqI-g6-MAV"/>
51+
<constraint firstItem="a2q-wM-NML" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="cTi-Vf-lIe"/>
52+
<constraint firstItem="Z4l-DI-rS9" firstAttribute="height" secondItem="iN0-l3-epB" secondAttribute="height" id="djY-u4-4bm"/>
53+
<constraint firstItem="Z4l-DI-rS9" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="eFq-01-vOg"/>
54+
<constraint firstItem="NNd-8B-dbM" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="kZh-lS-e9K"/>
55+
<constraint firstItem="a2q-wM-NML" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="mwv-Xz-PoN"/>
56+
<constraint firstItem="NNd-8B-dbM" firstAttribute="width" secondItem="iN0-l3-epB" secondAttribute="width" id="rC1-WX-8f2"/>
57+
<constraint firstItem="NNd-8B-dbM" firstAttribute="height" secondItem="iN0-l3-epB" secondAttribute="height" id="xeQ-o2-cJE"/>
58+
</constraints>
59+
<variation key="default">
60+
<mask key="constraints">
61+
<exclude reference="RqI-g6-MAV"/>
62+
</mask>
63+
</variation>
64+
</view>
65+
</objects>
66+
<resources>
67+
<image name="SelectorIcon" width="16" height="8"/>
68+
</resources>
69+
</document>

iOSFormUtils/ValidatedFormInput.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public protocol ValidatedFormInputDataSource {
6464
// MARK: Extensions
6565
extension FormInput: ValidatedFormInput {
6666
public func validateFormat() -> Bool {
67-
if let dataSource = validationDataSource {
67+
if let _ = validationDataSource {
6868
switch validationDataSource.validationTypeForInput(self) {
6969
case .NotBlank :
7070
if (0 < self.text!.characters.count) {

0 commit comments

Comments
 (0)