Commit 387a250e authored by Zandor Smith's avatar Zandor Smith 💻

Add AAPickerView dependancy.

parent 8dacb443
......@@ -270,12 +270,14 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-GeneralToolsFramework_Example/Pods-GeneralToolsFramework_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/AAPickerView/AAPickerView.framework",
"${BUILT_PRODUCTS_DIR}/Connectivity/Connectivity.framework",
"${BUILT_PRODUCTS_DIR}/GeneralToolsFramework/GeneralToolsFramework.framework",
"${BUILT_PRODUCTS_DIR}/PINCache/PINCache.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AAPickerView.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Connectivity.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GeneralToolsFramework.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PINCache.framework",
......
PODS:
- Connectivity (3.1.0)
- GeneralToolsFramework (1.3.0):
- AAPickerView (1.0)
- Connectivity (3.3.3)
- GeneralToolsFramework (1.6.5):
- AAPickerView
- Connectivity (~> 3.0)
- PINCache
- PINCache (2.3)
......@@ -9,7 +11,8 @@ DEPENDENCIES:
- GeneralToolsFramework (from `../`)
SPEC REPOS:
https://github.com/cocoapods/specs.git:
trunk:
- AAPickerView
- Connectivity
- PINCache
......@@ -18,10 +21,11 @@ EXTERNAL SOURCES:
:path: "../"
SPEC CHECKSUMS:
Connectivity: b900acf9c33029dd441ca0c1d5cf6cbdd7c9ee0b
GeneralToolsFramework: 6c6cd8a5838729e12484e06fac74d536ff6fccf4
AAPickerView: 32334007f7bb541db2b2f8663806f0a6636fdfeb
Connectivity: 4ffcb7456939268de2431c230a3ff015d4cbcfa9
GeneralToolsFramework: 0de0d7b8c3c7b941274debf44f84dc41b3de5ca4
PINCache: ce36ed282031b92fc7733ffe831f474ff80fddc2
PODFILE CHECKSUM: 8be6009e7d309a8d0cef2f1323298cf6b59c87c4
COCOAPODS: 1.7.5
COCOAPODS: 1.8.4
//
// AAPickerView+Helper.swift
// AAPickerView
//
// Created by Engr. Ahsan Ali on 04/02/2017.
// Copyright (c) 2017 AA-Creations. All rights reserved.
//
/// Picker View type
///
/// - StringPicker: string picker
/// - DatePicker: date picker
public enum AAPickerType {
case string(data: [String])
case date
}
//MARK: UIPickerViewDelegate
extension AAPickerView: UIPickerViewDelegate, UIPickerViewDataSource {
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return stringPickerData.count
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
open func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let label = pickerRow
label.text = stringPickerData[row]
return label
}
public func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return heightForRow
}
public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
valueDidChange?(row)
sendActions(for: .valueChanged)
}
}
//
// AAPickerView.swift
// AAPickerView
//
// Created by Engr. Ahsan Ali on 01/06/2017.
// Copyright (c) 2017 AA-Creations. All rights reserved.
//
/// MARK:- AAPickerView
open class AAPickerView: UITextField {
/// Callback for end editing
open var valueDidSelected: ((Any) -> Void)?
/// Callback for value change
open var valueDidChange: ((Any) -> Void)?
open var pickerType: AAPickerType = .date {
didSet {
switch pickerType {
case .date:
datePicker = UIDatePicker()
case .string(let stringData):
stringPicker = UIPickerView()
stringPickerData = stringData
}
inputAccessoryView = toolbar
}
}
// For DatePicker
open var dateFormatter = DateFormatter()
open var datePicker: UIDatePicker? {
get {
return self.inputView as? UIDatePicker
}
set {
inputView = newValue
dateFormatter.dateFormat = "MM/dd/YYYY"
}
}
// For String Picker
var stringPickerData = [String]()
open var heightForRow: CGFloat = 30
open var pickerRow: UILabel {
let pickerLabel = UILabel()
pickerLabel.textColor = .black
pickerLabel.font = UIFont(name: "HelveticaNeue", size: 20)
pickerLabel.textAlignment = .center
pickerLabel.sizeToFit()
return pickerLabel
}
open var stringPicker: UIPickerView? {
get {
return self.inputView as? UIPickerView
}
set(picker) {
picker?.delegate = self
inputView = picker
}
}
// Configurations
open var toolbar: UIToolbar {
let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.isTranslucent = true
toolBar.tintColor = .blue
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done,
target: self,
action: #selector(doneAction))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
target: nil,
action: nil)
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel,
target: self,
action: #selector(cancelAction))
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
inputAccessoryView = toolBar
return toolBar
}
@objc func doneAction() {
switch pickerType {
case .date:
let date = datePicker!.date
self.text = dateFormatter.string(from: date)
valueDidSelected?(date)
case .string:
let row = stringPicker!.selectedRow(inComponent: 0)
self.text = stringPickerData[row]
valueDidSelected?(row)
}
sendActions(for: .editingDidEnd)
resignFirstResponder()
}
@objc func cancelAction() {
resignFirstResponder()
}
}
Copyright (c) 2017 Engr. Ahsan Ali <hafiz.m.ahsan.ali@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# Table of Contents
- [AAPickerView](#section-id-4)
- [Description](#section-id-10)
- [Demonstration](#section-id-16)
- [Requirements](#section-id-26)
- [Installation](#section-id-32)
- [CocoaPods](#section-id-37)
- [Carthage](#section-id-63)
- [Manual Installation](#section-id-82)
- [Getting Started](#section-id-87)
- [Create instance of AAPickerView](#section-id-90)
- [Define picker type](#section-id-104)
- [Customise the toolbar](#section-id-112)
- [Customise StringPicker Label](#section-id-132)
- [Customise UIDatePicker & DateFormatter](#section-id-150)
- [Listen changes thorough callbacks](#section-id-151)
- [Contributions & License](#section-id-156)
<div id='section-id-4'/>
#AAPickerView
[![Swift 3.0](https://img.shields.io/badge/Swift-3.0-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![CocoaPods](https://img.shields.io/cocoapods/v/AAPickerView.svg)](http://cocoadocs.org/docsets/AAPickerView) [![License MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat)](https://github.com/Carthage/Carthage) [![Build Status](https://travis-ci.org/EngrAhsanAli/AAPickerView.svg?branch=master)](https://travis-ci.org/EngrAhsanAli/AAPickerView)
![License MIT](https://img.shields.io/github/license/mashape/apistatus.svg) [![CocoaPods](https://img.shields.io/cocoapods/p/AAPickerView.svg)]()
<div id='section-id-10'/>
##Description
AAPickerView is simple and easy-to-use implementation for `UITextField` to use as `UIPickerView` and `UIDatePicker` written in swift. It allows to transform `UITextField` as `UIPickerView` and `UIDatePicker` to pick data easily. It is designed to present a picker view to select data in `UITextField`.
<div id='section-id-16'/>
##Demonstration
![](https://github.com/EngrAhsanAli/AAPickerView/blob/master/Screenshots/demo.gif)
To run the example project, clone the repo, and run `pod install` from the Example directory first.
<div id='section-id-26'/>
##Requirements
- iOS 8.0+
- Xcode 8.0+
<div id='section-id-32'/>
# Installation
`AAPickerView` can be installed using CocoaPods, Carthage, or manually.
<div id='section-id-37'/>
##CocoaPods
`AAPickerView` is available through [CocoaPods](http://cocoapods.org). To install CocoaPods, run:
`$ gem install cocoapods`
Then create a Podfile with the following contents:
```
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
target '<Your Target Name>' do
// Swift 3.2+ Compatibility
pod 'AAPickerView'
// Swift 4 Compatibility
pod 'AAPickerView', '~> 0.1.2'
end
```
Finally, run the following command to install it:
```
$ pod install
```
<div id='section-id-63'/>
##Carthage
To install Carthage, run (using Homebrew):
```
$ brew update
$ brew install carthage
```
Then add the following line to your Cartfile:
```
github "EngrAhsanAli/AAPickerView" "master"
```
Then import the library in all files where you use it:
```swift
import AAPickerView
```
<div id='section-id-82'/>
##Manual Installation
If you prefer not to use either of the above mentioned dependency managers, you can integrate `AAPickerView` into your project manually by adding the files contained in the Classes folder to your project.
<div id='section-id-87'/>
#Getting Started
----------
<div id='section-id-90'/>
##Create instance of AAPickerView
You just need to assign `AAPickerView` class to your `UITextField` and make the outlet:
```swift
@IBOutlet weak var picker: AAPickerView!
```
Now your `UITextField` is transformed as a picker view as `AAPickerView`.
<div id='section-id-104'/>
##Define picker type
Define type of picker you want to use in your text field. There are two types of pickers available in `AAPickerView` that are:
- `StringPicker` for `UIPickerView`
- `DatePicker` for `UIDatePicker`
Assign one of them as follow:
```swift
picker1.pickerType = .StringPicker
picker2.pickerType = .DatePicker
```
<div id='section-id-112'/>
##Customise the toolbar
You can change `UIToolbar` colours like:
```swift
picker.toolbar.barTintColor = .darkGray
picker.toolbar.tintColor = .black
```
<div id='section-id-132'/>
##Customise StringPicker Label
You can get and customise the `StringPicker` label as `UILabel`:
```swift
let label = picker.pickerRow
label.font = UIFont(name: "American Typewriter", size: 30)
```
<div id='section-id-150'/>
##Customise UIDatePicker & DateFormatter
You can get your `UIDatePicker` and `DateFormatter` which is using behind your `UITextField` as:
```swift
let datePicker = picker.datePicker
datePicker?.datePickerMode = .date
let dateFormatter = picker.dateFormatter
dateFormatter.dateFormat = "dd/MM/YYYY"
```
<div id='section-id-151'/>
##Listen changes thorough callbacks
You can listen the changes of data simply by using the following callback methods:
- StringPicker:
```swift
picker.stringDidChange = { index in
print("selectedString ", self.stringData[index])
}
```
- DatePicker
```swift
picker.dateDidChange = { date in
print("selectedDate ", date )
}
```
<div id='section-id-156'/>
#Contributions & License
`AAPickerView` is available under the MIT license. See the [LICENSE](./LICENSE) file for more info.
Pull requests are welcome! The best contributions will consist of substitutions or configurations for classes/methods known to block the main thread during a typical app lifecycle.
I would love to know if you are using `AAPickerView` in your app, send an email to [Engr. Ahsan Ali](mailto:hafiz.m.ahsan.ali@gmail.com)
......@@ -54,10 +54,18 @@ public class Connectivity: NSObject {
public private(set) var currentInterface: Interface = .other
/// Regex expected to match connectivity URL response
public var expectedResponseRegEx = ".*?<BODY>.*?Success.*?</BODY>.*"
public var expectedResponseRegEx = ".*?<BODY>.*?Success.*?</BODY>.*" {
didSet {
updateValidator(for: validationMode)
}
}
/// Response expected from connectivity URLs
public var expectedResponseString = "Success"
public var expectedResponseString = "Success" {
didSet {
updateValidator(for: validationMode)
}
}
/// Whether or not to use System Configuration or Network (on iOS 12+) framework.
public var framework: Connectivity.Framework = .systemConfiguration
......@@ -109,6 +117,20 @@ public class Connectivity: NSObject {
/// Reachability instance for checking network adapter status
private let reachability: Reachability
/// Can be used to set a custom validator conforming to `ConnectivityResponseValidator`
public var responseValidator: ConnectivityResponseValidator =
ConnectivityResponseContainsStringValidator()
/// Returns the appropriate validator for the current validation mode.
private var responseValidatorFactory: ResponseValidatorFactory {
return ResponseValidatorFactory(
validationMode: validationMode,
expectedResponse: expectedResponseString,
regEx: expectedResponseRegEx,
customValidator: responseValidator
)
}
/// Status of the current connection
public var status: ConnectivityStatus = .determining
......@@ -125,7 +147,11 @@ public class Connectivity: NSObject {
}()
/// Method used to determine whether response content is valid
public var validationMode: ValidationMode = .containsExpectedResponseString
public var validationMode: ValidationMode = .containsExpectedResponseString {
didSet {
updateValidator(for: validationMode)
}
}
/// Callback to invoke when connected
public var whenConnected: NetworkConnected?
......@@ -177,21 +203,27 @@ public extension Connectivity {
let totalChecks: Int = connectivityURLs.count
// Connectivity check callback
let completionHandler: (Data?, URLResponse?, Error?) -> Void = { [weak self] (data, response, error) in
let connectivityCheckSuccess = self?.connectivityCheckSucceeded(data: data) ?? false
connectivityCheckSuccess ? (successfulChecks += 1) : (failedChecks += 1)
dispatchGroup.leave()
// Abort early if enough tasks have completed successfully
self?.cancelConnectivityCheck(pendingTasks: tasks, successfulChecks: successfulChecks,
totalChecks: totalChecks)
let completionHandlerForUrl: (URL) -> ((Data?, URLResponse?, Error?) -> Void) = { url in
return { [weak self] (data, response, error) in
let connectivityCheckSuccess = self?.connectivityCheckSucceeded(
for: url,
response: response,
data: data
) ?? false
connectivityCheckSuccess ? (successfulChecks += 1) : (failedChecks += 1)
dispatchGroup.leave()
// Abort early if enough tasks have completed successfully
self?.cancelConnectivityCheck(pendingTasks: tasks, successfulChecks: successfulChecks,
totalChecks: totalChecks)
}
}
// Check each of the specified URLs in turn
tasks = connectivityURLs.map({
if let urlRequest = authorizedURLRequest(with: $0) {
return session.dataTask(with: urlRequest, completionHandler: completionHandler)
return session.dataTask(with: urlRequest, completionHandler: completionHandlerForUrl($0))
}
return session.dataTask(with: $0, completionHandler: completionHandler)
return session.dataTask(with: $0, completionHandler: completionHandlerForUrl($0))
})
tasks.forEach({ task in
......@@ -300,34 +332,27 @@ private extension Connectivity {
}
/// Determines whether or not the connectivity check was successful.
private func connectivityCheckSucceeded(data: Data?) -> Bool {
guard let data = data, let responseString = String(data: data, encoding: .utf8) else {
return false
}
let validator = ConnectivityResponseValidator(validationMode: validationMode)
let result = (validationMode == .matchesRegularExpression)
? validator.isValid(expected: expectedResponseRegEx, responseString: responseString)
: validator.isValid(expected: expectedResponseString, responseString: responseString)
return result
private func connectivityCheckSucceeded(for url: URL, response: URLResponse?, data: Data?) -> Bool {
let validator = responseValidatorFactory.manufacture()
return validator.isResponseValid(url: url, response: response, data: data)
}
/// Set of connectivity URLs used by default if none are otherwise specified.
static func defaultConnectivityURLs(shouldUseHTTPS: Bool) -> [URL] {
var result: [URL] = []
let connectivityDomains: [String] = (shouldUseHTTPS)
? [ "www.apple.com" ] // Replace with custom URLs
: [ "www.apple.com",
"apple.com",
"www.appleiphonecell.com",
"www.itools.info",
"www.ibook.info",
"www.airport.us",
"www.thinkdifferent.us"
]
let connectivityPath = "/library/test/success.html"
let httpProtocol = (isHTTPSOnly) ? "https" : "http"
for domain in connectivityDomains {
if let connectivityURL = URL(string: "\(httpProtocol)://\(domain)\(connectivityPath)") {
let connectivityURLs: [String] = (shouldUseHTTPS)
? [ "https://www.apple.com/library/test/success.html",
"https://captive.apple.com/hotspot-detect.html" ] // Replace with custom URLs
: [ "http://www.apple.com/library/test/success.html",
"http://apple.com/library/test/success.html",
"http://www.appleiphonecell.com/library/test/success.html",
"http://www.itools.info/library/test/success.html",
"http://www.ibook.info/library/test/success.html",
"http://www.airport.us/library/test/success.html",
"http://www.thinkdifferent.us/library/test/success.html",
"http://captive.apple.com/hotspot-detect.html" ]
for connectivityURLStr in connectivityURLs {
if let connectivityURL = URL(string: connectivityURLStr) {
result.append(connectivityURL)
}
}
......@@ -537,6 +562,12 @@ private extension Connectivity {
}
}
/// Updates the validator when the validation mode changes.
func updateValidator(for validationMode: ValidationMode) {
let validator = responseValidatorFactory.manufacture()
self.responseValidator = validator
}