├── SPPinView
├── ezgif.com-video-to-gif.gif
├── SPPinView
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Helper
│ │ ├── GradientView
│ │ │ └── GradientView.swift
│ │ ├── UIView
│ │ │ └── SPView.swift
│ │ ├── SPView.swift
│ │ └── SPKeyBoardAvoiding
│ │ │ └── SPKeyBoardAvoiding.swift
│ ├── ApplicationDelegate
│ │ └── AppDelegate.swift
│ ├── Controller
│ │ └── ViewController.swift
│ ├── PinView
│ │ ├── Controller
│ │ │ └── ViewController.swift
│ │ ├── Model
│ │ │ └── SPPinView.swift
│ │ └── View
│ │ │ └── Base.lproj
│ │ │ └── Main.storyboard
│ ├── Info.plist
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ ├── ThirdParty
│ │ └── SPKeyBoardAvoiding
│ │ │ └── SPKeyBoardAvoiding.swift
│ ├── Model
│ │ └── SPPinView.swift
│ └── View
│ │ └── Base.lproj
│ │ └── Main.storyboard
└── SPPinView.xcodeproj
│ ├── xcshareddata
│ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ │ └── SPPinView.xcscheme
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── user.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ ├── xcuserdata
│ └── user.xcuserdatad
│ │ ├── xcschemes
│ │ └── xcschememanagement.plist
│ │ └── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ └── project.pbxproj
└── README.md
/SPPinView/ezgif.com-video-to-gif.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssowri1/SPPinView/HEAD/SPPinView/ezgif.com-video-to-gif.gif
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/SPPinView/SPPinView.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssowri1/SPPinView/HEAD/SPPinView/SPPinView.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SPPinView/SPPinView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Helper/GradientView/GradientView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * GradientView
3 | * This GradientView is used to extend our gradient functionlities.
4 | * @category SPPinView
5 | * @package com.SPPinView
6 | * @version 1.0
7 | * @author ssowri1
8 | * @copyright Copyright (C) 2019 ssowri1. All rights reserved.
9 | */
10 | import UIKit
11 | class GradientView: UIView {
12 | // gradine layer
13 | var gradientLayer: CAGradientLayer?
14 | class func layerClass() -> CAGradientLayer {
15 | return CAGradientLayer()
16 | }
17 | func gradientLay() -> CAGradientLayer {
18 | return gradientLayer!
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView.xcodeproj/xcuserdata/user.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SPPinView.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | CEAA3B01221FE3550021271B
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/ApplicationDelegate/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * AppDelegate
3 | * This AppDelegate is singleon of our project.
4 | * @category SPTouchID
5 | * @package com.SPPinView
6 | * @version 1.0
7 | * @author ssowri1
8 | * @copyright Copyright (C) 2019 ssowri1. All rights reserved.
9 | */
10 | import UIKit
11 |
12 | @UIApplicationMain
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 | var window: UIWindow?
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Helper/UIView/SPView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * GradientView
3 | * This UIView extension is used to extend our UIView functionlities.
4 | * @category SPPinView
5 | * @package com.SPPinView
6 | * @version 1.0
7 | * @author ssowri1
8 | * @copyright Copyright (C) 2019 ssowri1. All rights reserved.
9 | */
10 | import UIKit
11 | extension UIView {
12 | /// To shake the view
13 | func shake() {
14 | let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
15 | animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
16 | animation.duration = 0.6
17 | animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0]
18 | layer.add(animation, forKey: "shake")
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Helper/SPView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * AppDelegate
3 | * This UIView extension is used to extend our UIView functionlities.
4 | * @category SPPinView
5 | * @package com.SPPinView
6 | * @version 1.0
7 | * @author ssowri1
8 | * @copyright Copyright (C) 2019 ssowri1. All rights reserved.
9 | */
10 | import UIKit
11 | class GradientView: UIView {
12 | var gradientLayer: CAGradientLayer?
13 | class func layerClass() -> CAGradientLayer {
14 | return CAGradientLayer()
15 | }
16 | func gradientLay() -> CAGradientLayer {
17 | return gradientLayer!
18 | }
19 | }
20 | extension UIView {
21 | func shake() {
22 | let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
23 | animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
24 | animation.duration = 0.6
25 | animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0]
26 | layer.add(animation, forKey: "shake")
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Controller/ViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * SPPinView
3 | * This SPPinView is main class to handle the examples passcode or pinview opertaions
4 | * @category SPPinView
5 | * @package com.SPPinView
6 | * @version 1.0
7 | * @author ssowri1
8 | * @copyright Copyright (C) 2019 ssowri1. All rights reserved.
9 | */
10 | import UIKit
11 | class ViewController: UIViewController {
12 | @IBOutlet weak var pinView: SPPinView!
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 | changeAttributes()
16 | }
17 | func changeAttributes() {
18 | /// Constraint to pinview charecter counts.
19 | pinView.pinCount = 4
20 | /// Change the password format whether it is a secure text or non sequre text.
21 | pinView.shouldSecureText = false
22 | /// Set the spacing of the password.
23 | pinView.spacing = 10
24 | pinView.becomeFirstResponder()
25 | }
26 | @IBAction func editingEnd(_ sender: SPPinView) {
27 | if sender.pinString != "1111" {
28 | sender.shakePin()
29 | } else {
30 | debugPrint("Pin ==>> ", sender.pinString)
31 | sender.resignFirstResponder()
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SPPinView
2 |
3 | ### SPPinView
4 |
5 | SPPinView extensively use for pin view or passcode view or OTP view.
6 |
7 | 
8 |
9 | **INSTALLATION**
10 |
11 | - Drag and drop the respecive folders into your project and initialize it.
12 | - Eventually, Add UIView on your stroyboard and change the subclass name as SPPinView.
13 | - Chill! That's it.
14 | - Additionally, You can change the properties like below
15 |
16 | //**** OPTIONAL ****//
17 | //****
18 | //**** Constraint to pinview charecter counts.
19 | pinView.pinCount = 4
20 | //**** Change the password format whether it is a secure text or non sequre text.
21 | pinView.shouldSecureText = false
22 | //**** Set the spacing of the password.
23 | pinView.spacing = 10
24 |
25 | ## Authors
26 |
27 | [Ssowri1](https://github.com/ssowri1)
28 |
29 | ## License
30 |
31 | This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details
32 |
33 | ### Support or Contact
34 |
35 | Having trouble with Pages? Kindly [contact support](https://github.com/contact) and we’ll help you sort it out.
36 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/PinView/Controller/ViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * SPPinView
3 | * This SPPinView is main class to handle the examples passcode or pinview opertaions
4 | * @category SPPinView
5 | * @package com.SPPinView
6 | * @version 1.0
7 | * @author ssowri1
8 | * @copyright Copyright (C) 2019 ssowri1. All rights reserved.
9 | */
10 | import UIKit
11 | class ViewController: UIViewController {
12 | @IBOutlet weak var pinView: SPPinView!
13 | //MARK:- View life cycle methods
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 | changeAttributes()
17 | }
18 | //MARK:- Custom actions
19 | func changeAttributes() {
20 | /// Constraint to pinview charecter counts.
21 | pinView.pinCount = 4
22 | /// Change the password format whether it is a secure text or non sequre text.
23 | pinView.shouldSecureText = false
24 | /// Set the spacing of the password.
25 | pinView.spacing = 10
26 | /// To dismiss the keyboard
27 | pinView.becomeFirstResponder()
28 | }
29 | //MARK:- IB Actions
30 | @IBAction func editingEnd(_ sender: SPPinView) {
31 | if sender.pinString != "1111" {
32 | sender.shakePin()
33 | } else {
34 | sender.resignFirstResponder()
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/SPPinView/SPPinView/ThirdParty/SPKeyBoardAvoiding/SPKeyBoardAvoiding.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | // ssowri1
4 | //
5 | // Created by ssowri1 on 05/12/18.
6 | // Copyright © 2018 user. All rights reserved.
7 | //
8 | import UIKit
9 | class SPKeyBoardAvoiding: UIScrollView, UIScrollViewDelegate {
10 | override func awakeFromNib() {
11 | registerKeyboardNotifications()
12 | }
13 | /// Register Notification
14 | func registerKeyboardNotifications() {
15 | NotificationCenter.default.addObserver(self,
16 | selector:
17 | #selector(self.keyboardDidShow(notification:)),
18 | name: UIResponder.keyboardDidShowNotification,
19 | object: nil)
20 | NotificationCenter.default.addObserver(self,
21 | selector:
22 | #selector(self.keyboardWillHide(notification:)),
23 | name: UIResponder.keyboardWillHideNotification,
24 | object: nil)
25 | }
26 | /// Scrollview's ContentInset Change on Keyboard show
27 | @objc func keyboardDidShow(notification: NSNotification) {
28 | let userInfo: NSDictionary = (notification.userInfo as NSDictionary?)!
29 | let keyboardInfo = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue
30 | let keyboardSize = keyboardInfo?.cgRectValue.size
31 | let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: (keyboardSize?.height)!, right: 0)
32 | self.contentInset = contentInsets
33 | self.scrollIndicatorInsets = contentInsets
34 | }
35 | /// Scrollview's ContentInset Change on Keyboard hide
36 | @objc func keyboardWillHide(notification: NSNotification) {
37 | self.contentInset = UIEdgeInsets.zero
38 | self.scrollIndicatorInsets = UIEdgeInsets.zero
39 | }
40 | /// UnRegistering Notifications
41 | func unregisterKeyboardNotifications() {
42 | NotificationCenter.default.removeObserver(self)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Helper/SPKeyBoardAvoiding/SPKeyBoardAvoiding.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * SPKeyBoardAvoiding
3 | * This SPKeyBoardAvoiding is used to handle your UI.
4 | * @category SPPinView
5 | * @package com.SPPinView
6 | * @version 1.0
7 | * @author ssowri1
8 | * @copyright Copyright (C) 2019 ssowri1. All rights reserved.
9 | */
10 | import UIKit
11 | class SPKeyBoardAvoiding: UIScrollView, UIScrollViewDelegate {
12 | override func awakeFromNib() {
13 | registerKeyboardNotifications()
14 | }
15 | /// Register Notification
16 | func registerKeyboardNotifications() {
17 | NotificationCenter.default.addObserver(self,
18 | selector:
19 | #selector(self.keyboardDidShow(notification:)),
20 | name: UIResponder.keyboardDidShowNotification,
21 | object: nil)
22 | NotificationCenter.default.addObserver(self,
23 | selector:
24 | #selector(self.keyboardWillHide(notification:)),
25 | name: UIResponder.keyboardWillHideNotification,
26 | object: nil)
27 | }
28 | /// Scrollview's ContentInset Change on Keyboard show
29 | @objc func keyboardDidShow(notification: NSNotification) {
30 | let userInfo: NSDictionary = (notification.userInfo as NSDictionary?)!
31 | let keyboardInfo = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue
32 | let keyboardSize = keyboardInfo?.cgRectValue.size
33 | let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: (keyboardSize?.height)!, right: 0)
34 | self.contentInset = contentInsets
35 | self.scrollIndicatorInsets = contentInsets
36 | }
37 | /// Scrollview's ContentInset Change on Keyboard hide
38 | @objc func keyboardWillHide(notification: NSNotification) {
39 | self.contentInset = UIEdgeInsets.zero
40 | self.scrollIndicatorInsets = UIEdgeInsets.zero
41 | }
42 | /// UnRegistering Notifications
43 | func unregisterKeyboardNotifications() {
44 | NotificationCenter.default.removeObserver(self)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView.xcodeproj/xcuserdata/user.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
14 |
15 |
16 |
18 |
24 |
25 |
26 |
28 |
34 |
35 |
37 |
39 |
40 |
41 |
42 |
43 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView.xcodeproj/xcshareddata/xcschemes/SPPinView.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
69 |
70 |
71 |
72 |
78 |
80 |
86 |
87 |
88 |
89 |
91 |
92 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/Model/SPPinView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * AppDelegate
3 | * This SPPinView is handle all the process of our pin view features.
4 | * @category SPPinView
5 | * @package com.SPPinView
6 | * @version 1.0
7 | * @author ssowri1
8 | * @copyright Copyright (C) 2019 ssowri1. All rights reserved.
9 | */
10 | import UIKit
11 | @IBDesignable
12 | class SPPinView: UIControl, UIKeyInput {
13 | // To clear respective pinview texts which user tapped on.
14 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
15 | clear()
16 | becomeFirstResponder()
17 | }
18 | // to design how many number of pins would be shown
19 | @IBInspectable var pinCount: Int = 4 {
20 | didSet {
21 | setupViews()
22 | setNeedsDisplay()
23 | }
24 | }
25 | // to spacing between the pins
26 | @IBInspectable var spacing: CGFloat = 10 {
27 | didSet {
28 | pinStack.spacing = spacing
29 | setupViews()
30 | layoutIfNeeded()
31 | }
32 | }
33 | //
34 | // to hide the texts by enable true
35 | //
36 | @IBInspectable var shouldSecureText: Bool = false {
37 | didSet {
38 | setupViews()
39 | layoutIfNeeded()
40 | }
41 | }
42 | // to change the font of pins
43 | @IBInspectable var pinFont: UIFont = UIFont(name: "Futura-Medium", size: 21)! {
44 | didSet {
45 | setupViews()
46 | layoutIfNeeded()
47 | }
48 | }
49 | // to shake and clear if the pin is invalid
50 | public func shakePin() {
51 | clear()
52 | shake()
53 | }
54 | // to check whether it contains text or not
55 | var hasText: Bool {
56 | return nextTag > 1 ? true : false
57 | }
58 | // to print the entire pin at end of the editing
59 | var pinString: String = ""
60 | func insertText(_ text: String) {
61 | var secureText = text
62 | if shouldSecureText {
63 | secureText = "•"
64 | }
65 | if nextTag < (pinCount + 1) {
66 | (viewWithTag(nextTag)! as! PinView).key = text
67 | (viewWithTag(nextTag)! as! PinView).text = secureText
68 | (viewWithTag(nextTag)! as! PinView).font = pinFont
69 | nextTag += 1
70 | if nextTag == (pinCount + 1) {
71 | pinString = ""
72 | for index in 1.. 1 {
82 | nextTag -= 1
83 | (viewWithTag(nextTag)! as! PinView).key = ""
84 | (viewWithTag(nextTag)! as! PinView).text = ""
85 | }
86 | }
87 | func clear() {
88 | while nextTag > 1 {
89 | deleteBackward()
90 | }
91 | }
92 | // to change the keyboard type
93 | var keyboardType: UIKeyboardType {
94 | get {
95 | return .numberPad
96 | }
97 | set { }
98 | }
99 | // to identify the every pin with tag value
100 | private var nextTag = 1
101 | private lazy var pinStack: UIStackView = {
102 | let stv = UIStackView.init()
103 | stv.axis = .horizontal
104 | stv.alignment = .center
105 | stv.translatesAutoresizingMaskIntoConstraints = false
106 | stv.distribution = .fill
107 | stv.spacing = spacing
108 | return stv
109 | }()
110 | override var canBecomeFirstResponder: Bool {
111 | return true
112 | }
113 | // for dynamic initialisation
114 | override init(frame: CGRect) {
115 | super.init(frame: frame)
116 | addSubViewToThisControl()
117 | self.setupViews()
118 | }
119 | // for storyboard initialisation
120 | required init?(coder aDecoder: NSCoder) {
121 | super.init(coder: aDecoder)
122 | addSubViewToThisControl()
123 | self.setupViews()
124 | }
125 | override func prepareForInterfaceBuilder() {
126 | super.prepareForInterfaceBuilder()
127 | addSubViewToThisControl()
128 | self.setupViews()
129 | }
130 | private func addSubViewToThisControl() {
131 | addSubview(pinStack)
132 | }
133 | // to configure the view elements
134 | func setupViews() {
135 | for pinView in pinStack.arrangedSubviews {
136 | pinView.removeFromSuperview()
137 | }
138 | for cons in constraints {
139 | if cons.firstAttribute == .width {
140 | cons.isActive = false
141 | }
142 | }
143 | layoutIfNeeded()
144 | for tag in 1...pinCount {
145 | let pin = PinView.init(frame: .zero)
146 | pin.tag = tag
147 | pin.translatesAutoresizingMaskIntoConstraints = false
148 | pinStack.addArrangedSubview(pin)
149 | }
150 | addConstraints([
151 | pinStack.centerXAnchor.constraint(equalTo: self.centerXAnchor),
152 | pinStack.centerYAnchor.constraint(equalTo: self.centerYAnchor),
153 | pinStack.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.7, constant: 0),
154 | pinStack.widthAnchor.constraint(equalTo: pinStack.heightAnchor, multiplier: CGFloat(pinCount), constant: (CGFloat(pinCount - 1) * spacing)),
155 | ])
156 | for pinn in pinStack.arrangedSubviews {
157 | guard let pin = pinn as? PinView else {return}
158 | pinStack.addConstraints([
159 | pin.heightAnchor.constraint(equalTo: pinStack.heightAnchor, multiplier: 1),
160 | pin.widthAnchor.constraint(equalTo: pin.heightAnchor, constant: 0)
161 | ])
162 | }
163 | }
164 | // private class of UITextField pin view
165 | private class PinView: UITextField {
166 | var key: String = "" {
167 | didSet {
168 | setupViews()
169 | }
170 | }
171 | var hassText: Bool {
172 | return key != ""
173 | }
174 | override var bounds: CGRect {
175 | didSet {
176 | setupViews()
177 | }
178 | }
179 | override init(frame: CGRect) {
180 | super.init(frame: frame)
181 | setupViews()
182 | }
183 | required init?(coder aDecoder: NSCoder) {
184 | fatalError("init(coder:) has not been implemented")
185 | }
186 | private func setupViews() {
187 | layer.cornerRadius = 5
188 | layer.masksToBounds = true
189 | backgroundColor = .lightGray
190 | textAlignment = .center
191 | textColor = .white
192 | isUserInteractionEnabled = false
193 | font = self.font
194 | if hassText {
195 | self.backgroundColor = .blue
196 | } else {
197 | self.layer.borderColor = UIColor.white.cgColor
198 | }
199 | }
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/PinView/Model/SPPinView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | * AppDelegate
3 | * This SPPinView is handle all the process of our pin view features.
4 | * @category SPPinView
5 | * @package com.SPPinView
6 | * @version 1.0
7 | * @author ssowri1
8 | * @copyright Copyright (C) 2019 ssowri1. All rights reserved.
9 | */
10 | import UIKit
11 | @IBDesignable
12 | class SPPinView: UIControl, UIKeyInput {
13 | // To clear respective pinview texts which user tapped on.
14 | override func touchesBegan(_ touches: Set, with event: UIEvent?) {
15 | clear()
16 | becomeFirstResponder()
17 | }
18 | // to design how many number of pins would be shown
19 | @IBInspectable var pinCount: Int = 4 {
20 | didSet {
21 | setupViews()
22 | setNeedsDisplay()
23 | }
24 | }
25 | // to spacing between the pins
26 | @IBInspectable var spacing: CGFloat = 10 {
27 | didSet {
28 | pinStack.spacing = spacing
29 | setupViews()
30 | layoutIfNeeded()
31 | }
32 | }
33 | // to hide the texts by enable true
34 | @IBInspectable var shouldSecureText: Bool = false {
35 | didSet {
36 | setupViews()
37 | layoutIfNeeded()
38 | }
39 | }
40 | // to change the font of pins
41 | @IBInspectable var pinFont: UIFont = UIFont(name: "Futura-Medium", size: 21)! {
42 | didSet {
43 | setupViews()
44 | layoutIfNeeded()
45 | }
46 | }
47 | // to shake and clear if the pin is invalid
48 | public func shakePin() {
49 | clear()
50 | shake()
51 | }
52 | // to check whether it contains text or not
53 | var hasText: Bool {
54 | return nextTag > 1 ? true : false
55 | }
56 | // to print the entire pin at end of the editing
57 | var pinString: String = ""
58 | func insertText(_ text: String) {
59 | var secureText = text
60 | if shouldSecureText {
61 | secureText = "•"
62 | }
63 | if nextTag < (pinCount + 1) {
64 | (viewWithTag(nextTag)! as! PinView).key = text
65 | (viewWithTag(nextTag)! as! PinView).text = secureText
66 | (viewWithTag(nextTag)! as! PinView).font = pinFont
67 | nextTag += 1
68 | if nextTag == (pinCount + 1) {
69 | pinString = ""
70 | for index in 1.. 1 {
80 | nextTag -= 1
81 | (viewWithTag(nextTag)! as! PinView).key = ""
82 | (viewWithTag(nextTag)! as! PinView).text = ""
83 | }
84 | }
85 | func clear() {
86 | while nextTag > 1 {
87 | deleteBackward()
88 | }
89 | }
90 | // to change the keyboard type
91 | var keyboardType: UIKeyboardType {
92 | get {
93 | return .numberPad
94 | }
95 | set { }
96 | }
97 | // to identify the every pin with tag value
98 | private var nextTag = 1
99 | private lazy var pinStack: UIStackView = {
100 | let stv = UIStackView.init()
101 | stv.axis = .horizontal
102 | stv.alignment = .center
103 | stv.translatesAutoresizingMaskIntoConstraints = false
104 | stv.distribution = .fill
105 | stv.spacing = spacing
106 | return stv
107 | }()
108 | override var canBecomeFirstResponder: Bool {
109 | return true
110 | }
111 | // for dynamic initialisation
112 | override init(frame: CGRect) {
113 | super.init(frame: frame)
114 | addSubViewToThisControl()
115 | self.setupViews()
116 | }
117 | // for storyboard initialisation
118 | required init?(coder aDecoder: NSCoder) {
119 | super.init(coder: aDecoder)
120 | addSubViewToThisControl()
121 | self.setupViews()
122 | }
123 | override func prepareForInterfaceBuilder() {
124 | super.prepareForInterfaceBuilder()
125 | addSubViewToThisControl()
126 | self.setupViews()
127 | }
128 | private func addSubViewToThisControl() {
129 | addSubview(pinStack)
130 | }
131 | // to configure the view elements
132 | func setupViews() {
133 | for pinView in pinStack.arrangedSubviews {
134 | pinView.removeFromSuperview()
135 | }
136 | for cons in constraints {
137 | if cons.firstAttribute == .width {
138 | cons.isActive = false
139 | }
140 | }
141 | layoutIfNeeded()
142 | for tag in 1...pinCount {
143 | let pin = PinView.init(frame: .zero)
144 | pin.tag = tag
145 | pin.translatesAutoresizingMaskIntoConstraints = false
146 | pinStack.addArrangedSubview(pin)
147 | }
148 | addConstraints([
149 | pinStack.centerXAnchor.constraint(equalTo: self.centerXAnchor),
150 | pinStack.centerYAnchor.constraint(equalTo: self.centerYAnchor),
151 | pinStack.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.7, constant: 0),
152 | pinStack.widthAnchor.constraint(equalTo: pinStack.heightAnchor, multiplier: CGFloat(pinCount), constant: (CGFloat(pinCount - 1) * spacing)),
153 | ])
154 | for pinn in pinStack.arrangedSubviews {
155 | guard let pin = pinn as? PinView else {return}
156 | pinStack.addConstraints([
157 | pin.heightAnchor.constraint(equalTo: pinStack.heightAnchor, multiplier: 1),
158 | pin.widthAnchor.constraint(equalTo: pin.heightAnchor, constant: 0)
159 | ])
160 | }
161 | }
162 | // private class of UITextField pin view
163 | private class PinView: UITextField {
164 | var key: String = "" {
165 | didSet {
166 | setupViews()
167 | }
168 | }
169 | var hassText: Bool {
170 | return key != ""
171 | }
172 | override var bounds: CGRect {
173 | didSet {
174 | setupViews()
175 | }
176 | }
177 | override init(frame: CGRect) {
178 | super.init(frame: frame)
179 | setupViews()
180 | }
181 | required init?(coder aDecoder: NSCoder) {
182 | fatalError("init(coder:) has not been implemented")
183 | }
184 | private func setupViews() {
185 | layer.cornerRadius = 5
186 | layer.masksToBounds = true
187 | backgroundColor = .lightGray
188 | textAlignment = .center
189 | textColor = .white
190 | isUserInteractionEnabled = false
191 | font = self.font
192 | if hassText {
193 | self.backgroundColor = .blue
194 | } else {
195 | self.layer.borderColor = UIColor.white.cgColor
196 | }
197 | }
198 | }
199 | }
200 |
201 | extension UIView {
202 | /// To shake the view
203 | func shake() {
204 | let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
205 | animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
206 | animation.duration = 0.6
207 | animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0]
208 | layer.add(animation, forKey: "shake")
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/View/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView/PinView/View/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/SPPinView/SPPinView.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | CE3F91D622A6891B00C41B70 /* SPView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3F91D522A6891B00C41B70 /* SPView.swift */; };
11 | CE85A1ED2224385900B5DA37 /* SPKeyBoardAvoiding.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE85A1EC2224385900B5DA37 /* SPKeyBoardAvoiding.swift */; };
12 | CEAA3B06221FE3550021271B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEAA3B05221FE3550021271B /* AppDelegate.swift */; };
13 | CEAA3B08221FE3550021271B /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEAA3B07221FE3550021271B /* ViewController.swift */; };
14 | CEAA3B0B221FE3550021271B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CEAA3B09221FE3550021271B /* Main.storyboard */; };
15 | CEAA3B0D221FE3570021271B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CEAA3B0C221FE3570021271B /* Assets.xcassets */; };
16 | CEAA3B10221FE3570021271B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CEAA3B0E221FE3570021271B /* LaunchScreen.storyboard */; };
17 | CEAA3B18221FE5660021271B /* SPPinView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEAA3B17221FE5660021271B /* SPPinView.swift */; };
18 | CEBF8838224BB77A001FC1B4 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBF8837224BB77A001FC1B4 /* GradientView.swift */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | CE3F91D522A6891B00C41B70 /* SPView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPView.swift; sourceTree = ""; };
23 | CE85A1EC2224385900B5DA37 /* SPKeyBoardAvoiding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPKeyBoardAvoiding.swift; sourceTree = ""; };
24 | CEAA3B02221FE3550021271B /* SPPinView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SPPinView.app; sourceTree = BUILT_PRODUCTS_DIR; };
25 | CEAA3B05221FE3550021271B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
26 | CEAA3B07221FE3550021271B /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
27 | CEAA3B0A221FE3550021271B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
28 | CEAA3B0C221FE3570021271B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
29 | CEAA3B0F221FE3570021271B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
30 | CEAA3B11221FE3570021271B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
31 | CEAA3B17221FE5660021271B /* SPPinView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPPinView.swift; sourceTree = ""; };
32 | CEBF8837224BB77A001FC1B4 /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; };
33 | /* End PBXFileReference section */
34 |
35 | /* Begin PBXFrameworksBuildPhase section */
36 | CEAA3AFF221FE3550021271B /* Frameworks */ = {
37 | isa = PBXFrameworksBuildPhase;
38 | buildActionMask = 2147483647;
39 | files = (
40 | );
41 | runOnlyForDeploymentPostprocessing = 0;
42 | };
43 | /* End PBXFrameworksBuildPhase section */
44 |
45 | /* Begin PBXGroup section */
46 | CE3F91D322A688C200C41B70 /* PinView */ = {
47 | isa = PBXGroup;
48 | children = (
49 | CEBF883A224BB7EE001FC1B4 /* Model */,
50 | CEBF883F224BB82B001FC1B4 /* View */,
51 | CEBF883B224BB7F9001FC1B4 /* Controller */,
52 | );
53 | path = PinView;
54 | sourceTree = "";
55 | };
56 | CE3F91D422A6890800C41B70 /* UIView */ = {
57 | isa = PBXGroup;
58 | children = (
59 | CE3F91D522A6891B00C41B70 /* SPView.swift */,
60 | );
61 | path = UIView;
62 | sourceTree = "";
63 | };
64 | CE3F91D722A6896100C41B70 /* GradientView */ = {
65 | isa = PBXGroup;
66 | children = (
67 | CEBF8837224BB77A001FC1B4 /* GradientView.swift */,
68 | );
69 | path = GradientView;
70 | sourceTree = "";
71 | };
72 | CEAA3AF9221FE3550021271B = {
73 | isa = PBXGroup;
74 | children = (
75 | CEAA3B04221FE3550021271B /* SPPinView */,
76 | CEAA3B03221FE3550021271B /* Products */,
77 | );
78 | sourceTree = "";
79 | };
80 | CEAA3B03221FE3550021271B /* Products */ = {
81 | isa = PBXGroup;
82 | children = (
83 | CEAA3B02221FE3550021271B /* SPPinView.app */,
84 | );
85 | name = Products;
86 | sourceTree = "";
87 | };
88 | CEAA3B04221FE3550021271B /* SPPinView */ = {
89 | isa = PBXGroup;
90 | children = (
91 | CEBF883C224BB804001FC1B4 /* ApplicationDelegate */,
92 | CE3F91D322A688C200C41B70 /* PinView */,
93 | CEBF8839224BB7E7001FC1B4 /* Helper */,
94 | CEAA3B0C221FE3570021271B /* Assets.xcassets */,
95 | CEAA3B0E221FE3570021271B /* LaunchScreen.storyboard */,
96 | CEAA3B11221FE3570021271B /* Info.plist */,
97 | );
98 | path = SPPinView;
99 | sourceTree = "";
100 | };
101 | CEBF8839224BB7E7001FC1B4 /* Helper */ = {
102 | isa = PBXGroup;
103 | children = (
104 | CE3F91D422A6890800C41B70 /* UIView */,
105 | CEBF883E224BB824001FC1B4 /* SPKeyBoardAvoiding */,
106 | CE3F91D722A6896100C41B70 /* GradientView */,
107 | );
108 | path = Helper;
109 | sourceTree = "";
110 | };
111 | CEBF883A224BB7EE001FC1B4 /* Model */ = {
112 | isa = PBXGroup;
113 | children = (
114 | CEAA3B17221FE5660021271B /* SPPinView.swift */,
115 | );
116 | path = Model;
117 | sourceTree = "";
118 | };
119 | CEBF883B224BB7F9001FC1B4 /* Controller */ = {
120 | isa = PBXGroup;
121 | children = (
122 | CEAA3B07221FE3550021271B /* ViewController.swift */,
123 | );
124 | path = Controller;
125 | sourceTree = "";
126 | };
127 | CEBF883C224BB804001FC1B4 /* ApplicationDelegate */ = {
128 | isa = PBXGroup;
129 | children = (
130 | CEAA3B05221FE3550021271B /* AppDelegate.swift */,
131 | );
132 | path = ApplicationDelegate;
133 | sourceTree = "";
134 | };
135 | CEBF883E224BB824001FC1B4 /* SPKeyBoardAvoiding */ = {
136 | isa = PBXGroup;
137 | children = (
138 | CE85A1EC2224385900B5DA37 /* SPKeyBoardAvoiding.swift */,
139 | );
140 | path = SPKeyBoardAvoiding;
141 | sourceTree = "";
142 | };
143 | CEBF883F224BB82B001FC1B4 /* View */ = {
144 | isa = PBXGroup;
145 | children = (
146 | CEAA3B09221FE3550021271B /* Main.storyboard */,
147 | );
148 | path = View;
149 | sourceTree = "";
150 | };
151 | /* End PBXGroup section */
152 |
153 | /* Begin PBXNativeTarget section */
154 | CEAA3B01221FE3550021271B /* SPPinView */ = {
155 | isa = PBXNativeTarget;
156 | buildConfigurationList = CEAA3B14221FE3570021271B /* Build configuration list for PBXNativeTarget "SPPinView" */;
157 | buildPhases = (
158 | CEAA3AFE221FE3550021271B /* Sources */,
159 | CEAA3AFF221FE3550021271B /* Frameworks */,
160 | CEAA3B00221FE3550021271B /* Resources */,
161 | );
162 | buildRules = (
163 | );
164 | dependencies = (
165 | );
166 | name = SPPinView;
167 | productName = SPPinView;
168 | productReference = CEAA3B02221FE3550021271B /* SPPinView.app */;
169 | productType = "com.apple.product-type.application";
170 | };
171 | /* End PBXNativeTarget section */
172 |
173 | /* Begin PBXProject section */
174 | CEAA3AFA221FE3550021271B /* Project object */ = {
175 | isa = PBXProject;
176 | attributes = {
177 | LastSwiftUpdateCheck = 1010;
178 | LastUpgradeCheck = 1010;
179 | ORGANIZATIONNAME = user;
180 | TargetAttributes = {
181 | CEAA3B01221FE3550021271B = {
182 | CreatedOnToolsVersion = 10.1;
183 | };
184 | };
185 | };
186 | buildConfigurationList = CEAA3AFD221FE3550021271B /* Build configuration list for PBXProject "SPPinView" */;
187 | compatibilityVersion = "Xcode 9.3";
188 | developmentRegion = en;
189 | hasScannedForEncodings = 0;
190 | knownRegions = (
191 | en,
192 | Base,
193 | );
194 | mainGroup = CEAA3AF9221FE3550021271B;
195 | productRefGroup = CEAA3B03221FE3550021271B /* Products */;
196 | projectDirPath = "";
197 | projectRoot = "";
198 | targets = (
199 | CEAA3B01221FE3550021271B /* SPPinView */,
200 | );
201 | };
202 | /* End PBXProject section */
203 |
204 | /* Begin PBXResourcesBuildPhase section */
205 | CEAA3B00221FE3550021271B /* Resources */ = {
206 | isa = PBXResourcesBuildPhase;
207 | buildActionMask = 2147483647;
208 | files = (
209 | CEAA3B10221FE3570021271B /* LaunchScreen.storyboard in Resources */,
210 | CEAA3B0D221FE3570021271B /* Assets.xcassets in Resources */,
211 | CEAA3B0B221FE3550021271B /* Main.storyboard in Resources */,
212 | );
213 | runOnlyForDeploymentPostprocessing = 0;
214 | };
215 | /* End PBXResourcesBuildPhase section */
216 |
217 | /* Begin PBXSourcesBuildPhase section */
218 | CEAA3AFE221FE3550021271B /* Sources */ = {
219 | isa = PBXSourcesBuildPhase;
220 | buildActionMask = 2147483647;
221 | files = (
222 | CE85A1ED2224385900B5DA37 /* SPKeyBoardAvoiding.swift in Sources */,
223 | CEAA3B18221FE5660021271B /* SPPinView.swift in Sources */,
224 | CEAA3B08221FE3550021271B /* ViewController.swift in Sources */,
225 | CEAA3B06221FE3550021271B /* AppDelegate.swift in Sources */,
226 | CEBF8838224BB77A001FC1B4 /* GradientView.swift in Sources */,
227 | CE3F91D622A6891B00C41B70 /* SPView.swift in Sources */,
228 | );
229 | runOnlyForDeploymentPostprocessing = 0;
230 | };
231 | /* End PBXSourcesBuildPhase section */
232 |
233 | /* Begin PBXVariantGroup section */
234 | CEAA3B09221FE3550021271B /* Main.storyboard */ = {
235 | isa = PBXVariantGroup;
236 | children = (
237 | CEAA3B0A221FE3550021271B /* Base */,
238 | );
239 | name = Main.storyboard;
240 | sourceTree = "";
241 | };
242 | CEAA3B0E221FE3570021271B /* LaunchScreen.storyboard */ = {
243 | isa = PBXVariantGroup;
244 | children = (
245 | CEAA3B0F221FE3570021271B /* Base */,
246 | );
247 | name = LaunchScreen.storyboard;
248 | sourceTree = "";
249 | };
250 | /* End PBXVariantGroup section */
251 |
252 | /* Begin XCBuildConfiguration section */
253 | CEAA3B12221FE3570021271B /* Debug */ = {
254 | isa = XCBuildConfiguration;
255 | buildSettings = {
256 | ALWAYS_SEARCH_USER_PATHS = NO;
257 | CLANG_ANALYZER_NONNULL = YES;
258 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
259 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
260 | CLANG_CXX_LIBRARY = "libc++";
261 | CLANG_ENABLE_MODULES = YES;
262 | CLANG_ENABLE_OBJC_ARC = YES;
263 | CLANG_ENABLE_OBJC_WEAK = YES;
264 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
265 | CLANG_WARN_BOOL_CONVERSION = YES;
266 | CLANG_WARN_COMMA = YES;
267 | CLANG_WARN_CONSTANT_CONVERSION = YES;
268 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
270 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
271 | CLANG_WARN_EMPTY_BODY = YES;
272 | CLANG_WARN_ENUM_CONVERSION = YES;
273 | CLANG_WARN_INFINITE_RECURSION = YES;
274 | CLANG_WARN_INT_CONVERSION = YES;
275 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
276 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
277 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
278 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
279 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
280 | CLANG_WARN_STRICT_PROTOTYPES = YES;
281 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
282 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
283 | CLANG_WARN_UNREACHABLE_CODE = YES;
284 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
285 | CODE_SIGN_IDENTITY = "iPhone Developer";
286 | COPY_PHASE_STRIP = NO;
287 | DEBUG_INFORMATION_FORMAT = dwarf;
288 | ENABLE_STRICT_OBJC_MSGSEND = YES;
289 | ENABLE_TESTABILITY = YES;
290 | GCC_C_LANGUAGE_STANDARD = gnu11;
291 | GCC_DYNAMIC_NO_PIC = NO;
292 | GCC_NO_COMMON_BLOCKS = YES;
293 | GCC_OPTIMIZATION_LEVEL = 0;
294 | GCC_PREPROCESSOR_DEFINITIONS = (
295 | "DEBUG=1",
296 | "$(inherited)",
297 | );
298 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
299 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
300 | GCC_WARN_UNDECLARED_SELECTOR = YES;
301 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
302 | GCC_WARN_UNUSED_FUNCTION = YES;
303 | GCC_WARN_UNUSED_VARIABLE = YES;
304 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
305 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
306 | MTL_FAST_MATH = YES;
307 | ONLY_ACTIVE_ARCH = YES;
308 | SDKROOT = iphoneos;
309 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
310 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
311 | };
312 | name = Debug;
313 | };
314 | CEAA3B13221FE3570021271B /* Release */ = {
315 | isa = XCBuildConfiguration;
316 | buildSettings = {
317 | ALWAYS_SEARCH_USER_PATHS = NO;
318 | CLANG_ANALYZER_NONNULL = YES;
319 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
320 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
321 | CLANG_CXX_LIBRARY = "libc++";
322 | CLANG_ENABLE_MODULES = YES;
323 | CLANG_ENABLE_OBJC_ARC = YES;
324 | CLANG_ENABLE_OBJC_WEAK = YES;
325 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
326 | CLANG_WARN_BOOL_CONVERSION = YES;
327 | CLANG_WARN_COMMA = YES;
328 | CLANG_WARN_CONSTANT_CONVERSION = YES;
329 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
330 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
331 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
332 | CLANG_WARN_EMPTY_BODY = YES;
333 | CLANG_WARN_ENUM_CONVERSION = YES;
334 | CLANG_WARN_INFINITE_RECURSION = YES;
335 | CLANG_WARN_INT_CONVERSION = YES;
336 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
337 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
338 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
339 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
340 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
341 | CLANG_WARN_STRICT_PROTOTYPES = YES;
342 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
343 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
344 | CLANG_WARN_UNREACHABLE_CODE = YES;
345 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
346 | CODE_SIGN_IDENTITY = "iPhone Developer";
347 | COPY_PHASE_STRIP = NO;
348 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
349 | ENABLE_NS_ASSERTIONS = NO;
350 | ENABLE_STRICT_OBJC_MSGSEND = YES;
351 | GCC_C_LANGUAGE_STANDARD = gnu11;
352 | GCC_NO_COMMON_BLOCKS = YES;
353 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
354 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
355 | GCC_WARN_UNDECLARED_SELECTOR = YES;
356 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
357 | GCC_WARN_UNUSED_FUNCTION = YES;
358 | GCC_WARN_UNUSED_VARIABLE = YES;
359 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
360 | MTL_ENABLE_DEBUG_INFO = NO;
361 | MTL_FAST_MATH = YES;
362 | SDKROOT = iphoneos;
363 | SWIFT_COMPILATION_MODE = wholemodule;
364 | SWIFT_OPTIMIZATION_LEVEL = "-O";
365 | VALIDATE_PRODUCT = YES;
366 | };
367 | name = Release;
368 | };
369 | CEAA3B15221FE3570021271B /* Debug */ = {
370 | isa = XCBuildConfiguration;
371 | buildSettings = {
372 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
373 | CODE_SIGN_IDENTITY = "iPhone Developer";
374 | CODE_SIGN_STYLE = Automatic;
375 | DEVELOPMENT_TEAM = G9VMAQSBA5;
376 | INFOPLIST_FILE = SPPinView/Info.plist;
377 | LD_RUNPATH_SEARCH_PATHS = (
378 | "$(inherited)",
379 | "@executable_path/Frameworks",
380 | );
381 | PRODUCT_BUNDLE_IDENTIFIER = com.daimler.daimlerbustest;
382 | PRODUCT_NAME = "$(TARGET_NAME)";
383 | PROVISIONING_PROFILE_SPECIFIER = "";
384 | SWIFT_VERSION = 4.2;
385 | TARGETED_DEVICE_FAMILY = "1,2";
386 | };
387 | name = Debug;
388 | };
389 | CEAA3B16221FE3570021271B /* Release */ = {
390 | isa = XCBuildConfiguration;
391 | buildSettings = {
392 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
393 | CODE_SIGN_IDENTITY = "iPhone Developer";
394 | CODE_SIGN_STYLE = Automatic;
395 | DEVELOPMENT_TEAM = G9VMAQSBA5;
396 | INFOPLIST_FILE = SPPinView/Info.plist;
397 | LD_RUNPATH_SEARCH_PATHS = (
398 | "$(inherited)",
399 | "@executable_path/Frameworks",
400 | );
401 | PRODUCT_BUNDLE_IDENTIFIER = com.daimler.daimlerbustest;
402 | PRODUCT_NAME = "$(TARGET_NAME)";
403 | PROVISIONING_PROFILE_SPECIFIER = "";
404 | SWIFT_VERSION = 4.2;
405 | TARGETED_DEVICE_FAMILY = "1,2";
406 | };
407 | name = Release;
408 | };
409 | /* End XCBuildConfiguration section */
410 |
411 | /* Begin XCConfigurationList section */
412 | CEAA3AFD221FE3550021271B /* Build configuration list for PBXProject "SPPinView" */ = {
413 | isa = XCConfigurationList;
414 | buildConfigurations = (
415 | CEAA3B12221FE3570021271B /* Debug */,
416 | CEAA3B13221FE3570021271B /* Release */,
417 | );
418 | defaultConfigurationIsVisible = 0;
419 | defaultConfigurationName = Release;
420 | };
421 | CEAA3B14221FE3570021271B /* Build configuration list for PBXNativeTarget "SPPinView" */ = {
422 | isa = XCConfigurationList;
423 | buildConfigurations = (
424 | CEAA3B15221FE3570021271B /* Debug */,
425 | CEAA3B16221FE3570021271B /* Release */,
426 | );
427 | defaultConfigurationIsVisible = 0;
428 | defaultConfigurationName = Release;
429 | };
430 | /* End XCConfigurationList section */
431 | };
432 | rootObject = CEAA3AFA221FE3550021271B /* Project object */;
433 | }
434 |
--------------------------------------------------------------------------------