Repository: Root-vb/OTPFieldView
Branch: master
Commit: ed198372acc9
Files: 14
Total size: 43.0 KB
Directory structure:
gitextract_1c6mpg_h/
├── LICENSE
├── OTPFieldView/
│ ├── Info.plist
│ ├── OTPFieldView.h
│ ├── OTPFieldView.swift
│ └── OTPTextField.swift
├── OTPFieldView.podspec
├── OTPFieldView.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata/
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcuserdata/
│ │ └── vaibhavbhasin.xcuserdatad/
│ │ └── UserInterfaceState.xcuserstate
│ └── xcuserdata/
│ └── vaibhavbhasin.xcuserdatad/
│ └── xcschemes/
│ └── xcschememanagement.plist
├── OTPFieldViewTests/
│ ├── Info.plist
│ └── OTPFieldViewTests.swift
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 Vaibhav Bhasin
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.
================================================
FILE: OTPFieldView/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.1</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>
================================================
FILE: OTPFieldView/OTPFieldView.h
================================================
//
// OTPFieldView.h
// OTPFieldView
//
// Created by Vaibhav Bhasin on 10/09/19.
// Copyright © 2019 Vaibhav Bhasin. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for OTPFieldView.
FOUNDATION_EXPORT double OTPFieldViewVersionNumber;
//! Project version string for OTPFieldView.
FOUNDATION_EXPORT const unsigned char OTPFieldViewVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <OTPFieldView/PublicHeader.h>
================================================
FILE: OTPFieldView/OTPFieldView.swift
================================================
//
// OTPFieldView.swift
// OTPFieldView
//
// Created by Vaibhav Bhasin on 10/09/19.
// Copyright © 2019 Vaibhav Bhasin. All rights reserved.
//
// MIT License
//
// Copyright (c) 2019 Vaibhav Bhasin
//
// 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.
import UIKit
@objc public protocol OTPFieldViewDelegate: class {
func shouldBecomeFirstResponderForOTP(otpTextFieldIndex index: Int) -> Bool
func enteredOTP(otp: String)
func hasEnteredAllOTP(hasEnteredAll: Bool) -> Bool
}
@objc public enum DisplayType: Int {
case circular
case roundedCorner
case square
case diamond
case underlinedBottom
}
/// Different input type for OTP fields.
@objc public enum KeyboardType: Int {
case numeric
case alphabet
case alphaNumeric
}
@objc public class OTPFieldView: UIView {
/// Different display type for text fields.
public var displayType: DisplayType = .circular
public var fieldsCount: Int = 4
public var otpInputType: KeyboardType = .numeric
public var fieldFont: UIFont = UIFont.systemFont(ofSize: 20)
public var secureEntry: Bool = false
public var hideEnteredText: Bool = false
public var requireCursor: Bool = true
public var cursorColor: UIColor = UIColor.blue
public var fieldSize: CGFloat = 60
public var separatorSpace: CGFloat = 16
public var fieldBorderWidth: CGFloat = 1
public var shouldAllowIntermediateEditing: Bool = true
public var defaultBackgroundColor: UIColor = UIColor.clear
public var filledBackgroundColor: UIColor = UIColor.clear
public var defaultBorderColor: UIColor = UIColor.gray
public var filledBorderColor: UIColor = UIColor.clear
public var errorBorderColor: UIColor?
public weak var delegate: OTPFieldViewDelegate?
fileprivate var secureEntryData = [String]()
override public func awakeFromNib() {
super.awakeFromNib()
}
public func initializeUI() {
layer.masksToBounds = true
layoutIfNeeded()
initializeOTPFields()
layoutIfNeeded()
// Forcefully try to make first otp field as first responder
(viewWithTag(1) as? OTPTextField)?.becomeFirstResponder()
}
fileprivate func initializeOTPFields() {
secureEntryData.removeAll()
for index in stride(from: 0, to: fieldsCount, by: 1) {
let oldOtpField = viewWithTag(index + 1) as? OTPTextField
oldOtpField?.removeFromSuperview()
let otpField = getOTPField(forIndex: index)
addSubview(otpField)
secureEntryData.append("")
}
}
fileprivate func getOTPField(forIndex index: Int) -> OTPTextField {
let hasOddNumberOfFields = (fieldsCount % 2 == 1)
var fieldFrame = CGRect(x: 0, y: 0, width: fieldSize, height: fieldSize)
if hasOddNumberOfFields {
// Calculate from middle each fields x and y values so as to align the entire view in center
fieldFrame.origin.x = bounds.size.width / 2 - (CGFloat(fieldsCount / 2 - index) * (fieldSize + separatorSpace) + fieldSize / 2)
}
else {
// Calculate from middle each fields x and y values so as to align the entire view in center
fieldFrame.origin.x = bounds.size.width / 2 - (CGFloat(fieldsCount / 2 - index) * fieldSize + CGFloat(fieldsCount / 2 - index - 1) * separatorSpace + separatorSpace / 2)
}
fieldFrame.origin.y = (bounds.size.height - fieldSize) / 2
let otpField = OTPTextField(frame: fieldFrame)
otpField.delegate = self
otpField.tag = index + 1
otpField.font = fieldFont
// Set input type for OTP fields
switch otpInputType {
case .numeric:
otpField.keyboardType = .numberPad
case .alphabet:
otpField.keyboardType = .alphabet
case .alphaNumeric:
otpField.keyboardType = .namePhonePad
}
// Set the border values if needed
otpField.otpBorderColor = defaultBorderColor
otpField.otpBorderWidth = fieldBorderWidth
if requireCursor {
otpField.tintColor = cursorColor
}
else {
otpField.tintColor = UIColor.clear
}
// Set the default background color when text not set
otpField.backgroundColor = defaultBackgroundColor
// Finally create the fields
otpField.initalizeUI(forFieldType: displayType)
return otpField
}
fileprivate func isPreviousFieldsEntered(forTextField textField: UITextField) -> Bool {
var isTextFilled = true
var nextOTPField: UITextField?
// If intermediate editing is not allowed, then check for last filled field in forward direction.
if !shouldAllowIntermediateEditing {
for index in stride(from: 1, to: fieldsCount + 1, by: 1) {
let tempNextOTPField = viewWithTag(index) as? UITextField
if let tempNextOTPFieldText = tempNextOTPField?.text, tempNextOTPFieldText.isEmpty {
nextOTPField = tempNextOTPField
break
}
}
if let nextOTPField = nextOTPField {
isTextFilled = (nextOTPField == textField || (textField.tag) == (nextOTPField.tag - 1))
}
}
return isTextFilled
}
// Helper function to get the OTP String entered
fileprivate func calculateEnteredOTPSTring(isDeleted: Bool) {
if isDeleted {
_ = delegate?.hasEnteredAllOTP(hasEnteredAll: false)
// Set the default enteres state for otp entry
for index in stride(from: 0, to: fieldsCount, by: 1) {
var otpField = viewWithTag(index + 1) as? OTPTextField
if otpField == nil {
otpField = getOTPField(forIndex: index)
}
let fieldBackgroundColor = (otpField?.text ?? "").isEmpty ? defaultBackgroundColor : filledBackgroundColor
let fieldBorderColor = (otpField?.text ?? "").isEmpty ? defaultBorderColor : filledBorderColor
if displayType == .diamond || displayType == .underlinedBottom {
otpField?.shapeLayer.fillColor = fieldBackgroundColor.cgColor
otpField?.shapeLayer.strokeColor = fieldBorderColor.cgColor
} else {
otpField?.backgroundColor = fieldBackgroundColor
otpField?.layer.borderColor = fieldBorderColor.cgColor
}
}
}
else {
var enteredOTPString = ""
// Check for entered OTP
for index in stride(from: 0, to: secureEntryData.count, by: 1) {
if !secureEntryData[index].isEmpty {
enteredOTPString.append(secureEntryData[index])
}
}
if enteredOTPString.count == fieldsCount {
delegate?.enteredOTP(otp: enteredOTPString)
// Check if all OTP fields have been filled or not. Based on that call the 2 delegate methods.
let isValid = delegate?.hasEnteredAllOTP(hasEnteredAll: (enteredOTPString.count == fieldsCount)) ?? false
// Set the error state for invalid otp entry
for index in stride(from: 0, to: fieldsCount, by: 1) {
var otpField = viewWithTag(index + 1) as? OTPTextField
if otpField == nil {
otpField = getOTPField(forIndex: index)
}
if !isValid {
// Set error border color if set, if not, set default border color
otpField?.layer.borderColor = (errorBorderColor ?? filledBorderColor).cgColor
}
else {
otpField?.layer.borderColor = filledBorderColor.cgColor
}
}
}
}
}
}
extension OTPFieldView: UITextFieldDelegate {
public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
let shouldBeginEditing = delegate?.shouldBecomeFirstResponderForOTP(otpTextFieldIndex: (textField.tag - 1)) ?? true
if shouldBeginEditing {
return isPreviousFieldsEntered(forTextField: textField)
}
return shouldBeginEditing
}
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let replacedText = (textField.text as NSString?)?.replacingCharacters(in: range, with: string) ?? ""
// Check since only alphabet keyboard is not available in iOS
if !replacedText.isEmpty && otpInputType == .alphabet && replacedText.rangeOfCharacter(from: .letters) == nil {
return false
}
if replacedText.count >= 1 {
// If field has a text already, then replace the text and move to next field if present
secureEntryData[textField.tag - 1] = string
if hideEnteredText {
textField.text = " "
}
else {
if secureEntry {
textField.text = "•"
}
else {
textField.text = string
}
}
if displayType == .diamond || displayType == .underlinedBottom {
(textField as! OTPTextField).shapeLayer.fillColor = filledBackgroundColor.cgColor
(textField as! OTPTextField).shapeLayer.strokeColor = filledBorderColor.cgColor
}
else {
textField.backgroundColor = filledBackgroundColor
textField.layer.borderColor = filledBorderColor.cgColor
}
let nextOTPField = viewWithTag(textField.tag + 1)
if let nextOTPField = nextOTPField {
nextOTPField.becomeFirstResponder()
}
else {
textField.resignFirstResponder()
}
// Get the entered string
calculateEnteredOTPSTring(isDeleted: false)
}
else {
let currentText = textField.text ?? ""
if textField.tag > 1 && currentText.isEmpty {
if let prevOTPField = viewWithTag(textField.tag - 1) as? UITextField {
deleteText(in: prevOTPField)
}
} else {
deleteText(in: textField)
if textField.tag > 1 {
if let prevOTPField = viewWithTag(textField.tag - 1) as? UITextField {
prevOTPField.becomeFirstResponder()
}
}
}
}
return false
}
private func deleteText(in textField: UITextField) {
// If deleting the text, then move to previous text field if present
secureEntryData[textField.tag - 1] = ""
textField.text = ""
if displayType == .diamond || displayType == .underlinedBottom {
(textField as! OTPTextField).shapeLayer.fillColor = defaultBackgroundColor.cgColor
(textField as! OTPTextField).shapeLayer.strokeColor = defaultBorderColor.cgColor
} else {
textField.backgroundColor = defaultBackgroundColor
textField.layer.borderColor = defaultBorderColor.cgColor
}
textField.becomeFirstResponder()
// Get the entered string
calculateEnteredOTPSTring(isDeleted: true)
}
}
================================================
FILE: OTPFieldView/OTPTextField.swift
================================================
//
// OTPTextField.swift
// OTPFieldView
//
// Created by Vaibhav Bhasin on 10/09/19.
// Copyright © 2019 Vaibhav Bhasin. All rights reserved.
//
// MIT License
//
// Copyright (c) 2019 Vaibhav Bhasin
//
// 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.
import UIKit
@objc class OTPTextField: UITextField {
/// Border color info for field
public var otpBorderColor: UIColor = UIColor.black
/// Border width info for field
public var otpBorderWidth: CGFloat = 2
public var shapeLayer: CAShapeLayer!
override func awakeFromNib() {
super.awakeFromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
public func initalizeUI(forFieldType type: DisplayType) {
switch type {
case .circular:
layer.cornerRadius = bounds.size.width / 2
break
case .roundedCorner:
layer.cornerRadius = 4
break
case .square:
layer.cornerRadius = 0
break
case .diamond:
addDiamondMask()
break
case .underlinedBottom:
addBottomView()
break
}
// Basic UI setup
if type != .diamond && type != .underlinedBottom {
layer.borderColor = otpBorderColor.cgColor
layer.borderWidth = otpBorderWidth
}
autocorrectionType = .no
textAlignment = .center
if #available(iOS 12.0, *) {
textContentType = .oneTimeCode
}
}
override func deleteBackward() {
super.deleteBackward()
_ = delegate?.textField?(self, shouldChangeCharactersIn: NSMakeRange(0, 0), replacementString: "")
}
// Helper function to create diamond view
fileprivate func addDiamondMask() {
let path = UIBezierPath()
path.move(to: CGPoint(x: bounds.size.width / 2.0, y: 0))
path.addLine(to: CGPoint(x: bounds.size.width, y: bounds.size.height / 2.0))
path.addLine(to: CGPoint(x: bounds.size.width / 2.0, y: bounds.size.height))
path.addLine(to: CGPoint(x: 0, y: bounds.size.height / 2.0))
path.close()
let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
layer.mask = maskLayer
shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.lineWidth = otpBorderWidth
shapeLayer.fillColor = backgroundColor?.cgColor
shapeLayer.strokeColor = otpBorderColor.cgColor
layer.addSublayer(shapeLayer)
}
// Helper function to create a underlined bottom view
fileprivate func addBottomView() {
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: bounds.size.height))
path.addLine(to: CGPoint(x: bounds.size.width, y: bounds.size.height))
path.close()
shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.lineWidth = otpBorderWidth
shapeLayer.fillColor = backgroundColor?.cgColor
shapeLayer.strokeColor = otpBorderColor.cgColor
layer.addSublayer(shapeLayer)
}
}
================================================
FILE: OTPFieldView.podspec
================================================
Pod::Spec.new do |spec|
spec.name = "OTPFieldView"
spec.version = "1.0.1"
spec.summary = "A CocoaPods library for One Time Password View written in Swift"
spec.description = <<-DESC
This library helps you create One-Time-Password view for iOS Applications
DESC
spec.homepage = "https://github.com/Root-vb/OTPFieldView"
spec.license = { :type => "MIT", :file => "LICENSE" }
spec.author = { "Vaibhav Bhasin" => "vaibhavbhasin15@gmail.com" }
spec.ios.deployment_target = "10.3"
spec.swift_version = "5.0"
spec.source = { :git => "https://github.com/Root-vb/OTPFieldView.git", :tag => "#{spec.version}" }
spec.source_files = "OTPFieldView/**/*.{h,m,swift}"
end
================================================
FILE: OTPFieldView.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
13EDE57623278D8700B45FF6 /* OTPFieldView.h in Headers */ = {isa = PBXBuildFile; fileRef = 13EDE57423278D8700B45FF6 /* OTPFieldView.h */; settings = {ATTRIBUTES = (Public, ); }; };
13EDE57D23278DC400B45FF6 /* OTPFieldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EDE57C23278DC400B45FF6 /* OTPFieldView.swift */; };
13EDE57F23278E9A00B45FF6 /* OTPTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EDE57E23278E9A00B45FF6 /* OTPTextField.swift */; };
13EDE5872327A8C400B45FF6 /* OTPFieldViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13EDE5862327A8C400B45FF6 /* OTPFieldViewTests.swift */; };
13EDE5892327A8C400B45FF6 /* OTPFieldView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13EDE57123278D8700B45FF6 /* OTPFieldView.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
13EDE58A2327A8C400B45FF6 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 13EDE56823278D8700B45FF6 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 13EDE57023278D8700B45FF6;
remoteInfo = OTPFieldView;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
13EDE57123278D8700B45FF6 /* OTPFieldView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OTPFieldView.framework; sourceTree = BUILT_PRODUCTS_DIR; };
13EDE57423278D8700B45FF6 /* OTPFieldView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OTPFieldView.h; sourceTree = "<group>"; };
13EDE57523278D8700B45FF6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13EDE57C23278DC400B45FF6 /* OTPFieldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTPFieldView.swift; sourceTree = "<group>"; };
13EDE57E23278E9A00B45FF6 /* OTPTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTPTextField.swift; sourceTree = "<group>"; };
13EDE5842327A8C400B45FF6 /* OTPFieldViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OTPFieldViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
13EDE5862327A8C400B45FF6 /* OTPFieldViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTPFieldViewTests.swift; sourceTree = "<group>"; };
13EDE5882327A8C400B45FF6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
13EDE56E23278D8700B45FF6 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
13EDE5812327A8C400B45FF6 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
13EDE5892327A8C400B45FF6 /* OTPFieldView.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
13EDE56723278D8700B45FF6 = {
isa = PBXGroup;
children = (
13EDE57323278D8700B45FF6 /* OTPFieldView */,
13EDE5852327A8C400B45FF6 /* OTPFieldViewTests */,
13EDE57223278D8700B45FF6 /* Products */,
);
sourceTree = "<group>";
};
13EDE57223278D8700B45FF6 /* Products */ = {
isa = PBXGroup;
children = (
13EDE57123278D8700B45FF6 /* OTPFieldView.framework */,
13EDE5842327A8C400B45FF6 /* OTPFieldViewTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
13EDE57323278D8700B45FF6 /* OTPFieldView */ = {
isa = PBXGroup;
children = (
13EDE57423278D8700B45FF6 /* OTPFieldView.h */,
13EDE57523278D8700B45FF6 /* Info.plist */,
13EDE57C23278DC400B45FF6 /* OTPFieldView.swift */,
13EDE57E23278E9A00B45FF6 /* OTPTextField.swift */,
);
path = OTPFieldView;
sourceTree = "<group>";
};
13EDE5852327A8C400B45FF6 /* OTPFieldViewTests */ = {
isa = PBXGroup;
children = (
13EDE5862327A8C400B45FF6 /* OTPFieldViewTests.swift */,
13EDE5882327A8C400B45FF6 /* Info.plist */,
);
path = OTPFieldViewTests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
13EDE56C23278D8700B45FF6 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
13EDE57623278D8700B45FF6 /* OTPFieldView.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
13EDE57023278D8700B45FF6 /* OTPFieldView */ = {
isa = PBXNativeTarget;
buildConfigurationList = 13EDE57923278D8700B45FF6 /* Build configuration list for PBXNativeTarget "OTPFieldView" */;
buildPhases = (
13EDE56C23278D8700B45FF6 /* Headers */,
13EDE56D23278D8700B45FF6 /* Sources */,
13EDE56E23278D8700B45FF6 /* Frameworks */,
13EDE56F23278D8700B45FF6 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = OTPFieldView;
productName = OTPFieldView;
productReference = 13EDE57123278D8700B45FF6 /* OTPFieldView.framework */;
productType = "com.apple.product-type.framework";
};
13EDE5832327A8C400B45FF6 /* OTPFieldViewTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 13EDE58C2327A8C400B45FF6 /* Build configuration list for PBXNativeTarget "OTPFieldViewTests" */;
buildPhases = (
13EDE5802327A8C400B45FF6 /* Sources */,
13EDE5812327A8C400B45FF6 /* Frameworks */,
13EDE5822327A8C400B45FF6 /* Resources */,
);
buildRules = (
);
dependencies = (
13EDE58B2327A8C400B45FF6 /* PBXTargetDependency */,
);
name = OTPFieldViewTests;
productName = OTPFieldViewTests;
productReference = 13EDE5842327A8C400B45FF6 /* OTPFieldViewTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
13EDE56823278D8700B45FF6 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1030;
LastUpgradeCheck = 1030;
ORGANIZATIONNAME = "Vaibhav Bhasin";
TargetAttributes = {
13EDE57023278D8700B45FF6 = {
CreatedOnToolsVersion = 10.3;
LastSwiftMigration = 1030;
};
13EDE5832327A8C400B45FF6 = {
CreatedOnToolsVersion = 10.3;
};
};
};
buildConfigurationList = 13EDE56B23278D8700B45FF6 /* Build configuration list for PBXProject "OTPFieldView" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 13EDE56723278D8700B45FF6;
productRefGroup = 13EDE57223278D8700B45FF6 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
13EDE57023278D8700B45FF6 /* OTPFieldView */,
13EDE5832327A8C400B45FF6 /* OTPFieldViewTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
13EDE56F23278D8700B45FF6 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
13EDE5822327A8C400B45FF6 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
13EDE56D23278D8700B45FF6 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13EDE57D23278DC400B45FF6 /* OTPFieldView.swift in Sources */,
13EDE57F23278E9A00B45FF6 /* OTPTextField.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
13EDE5802327A8C400B45FF6 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
13EDE5872327A8C400B45FF6 /* OTPFieldViewTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
13EDE58B2327A8C400B45FF6 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 13EDE57023278D8700B45FF6 /* OTPFieldView */;
targetProxy = 13EDE58A2327A8C400B45FF6 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
13EDE57723278D8700B45FF6 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
13EDE57823278D8700B45FF6 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
13EDE57A23278D8700B45FF6 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 7X5CB8QV9R;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = OTPFieldView/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.Vaibhav.OTPFieldView;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
13EDE57B23278D8700B45FF6 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 7X5CB8QV9R;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = OTPFieldView/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.Vaibhav.OTPFieldView;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
13EDE58D2327A8C400B45FF6 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 7X5CB8QV9R;
INFOPLIST_FILE = OTPFieldViewTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.Vaibhav.OTPFieldViewTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
13EDE58E2327A8C400B45FF6 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 7X5CB8QV9R;
INFOPLIST_FILE = OTPFieldViewTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.Vaibhav.OTPFieldViewTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
13EDE56B23278D8700B45FF6 /* Build configuration list for PBXProject "OTPFieldView" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13EDE57723278D8700B45FF6 /* Debug */,
13EDE57823278D8700B45FF6 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
13EDE57923278D8700B45FF6 /* Build configuration list for PBXNativeTarget "OTPFieldView" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13EDE57A23278D8700B45FF6 /* Debug */,
13EDE57B23278D8700B45FF6 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
13EDE58C2327A8C400B45FF6 /* Build configuration list for PBXNativeTarget "OTPFieldViewTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
13EDE58D2327A8C400B45FF6 /* Debug */,
13EDE58E2327A8C400B45FF6 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 13EDE56823278D8700B45FF6 /* Project object */;
}
================================================
FILE: OTPFieldView.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:OTPFieldView.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: OTPFieldView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
================================================
FILE: OTPFieldView.xcodeproj/xcuserdata/vaibhavbhasin.xcuserdatad/xcschemes/xcschememanagement.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>OTPFieldView.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>OTPFieldViewTests.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict>
</dict>
</plist>
================================================
FILE: OTPFieldViewTests/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
================================================
FILE: OTPFieldViewTests/OTPFieldViewTests.swift
================================================
//
// OTPFieldViewTests.swift
// OTPFieldViewTests
//
// Created by Vaibhav Bhasin on 10/09/19.
// Copyright © 2019 Vaibhav Bhasin. All rights reserved.
//
import XCTest
class OTPFieldViewTests: XCTestCase {
override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
================================================
FILE: README.md
================================================
# OTPFieldView
One Time Password View for iOS. Built in Swift 5
<p align="left">
<a href="https://developer.apple.com/swift"><img src="https://img.shields.io/badge/Swift_5-compatible-4BC51D.svg?style=flat" alt="Swift 5 compatible" /></a>
<img src="https://img.shields.io/badge/platform-iOS-blue.svg?style=flat" alt="Platform iOS" />
<a href="https://raw.githubusercontent.com/maxsokolov/tablekit/master/LICENSE"><img src="http://img.shields.io/badge/license-MIT-blue.svg?style=flat" alt="License: MIT" /></a>
</p>
### Preview





## Installation
### CocoaPods
Add the following line to your Podfile:
```ruby
pod 'OTPFieldView'
```
Then run the following in the same directory as your Podfile:
```ruby
pod install
```
## Usage
### Code
```swift
@IBOutlet var otpTextFieldView: OTPFieldView!
func setupOtpView(){
self.otpTextFieldView.fieldsCount = 5
self.otpTextFieldView.fieldBorderWidth = 2
self.otpTextFieldView.defaultBorderColor = UIColor.black
self.otpTextFieldView.filledBorderColor = UIColor.green
self.otpTextFieldView.cursorColor = UIColor.red
self.otpTextFieldView.displayType = .underlinedBottom
self.otpTextFieldView.fieldSize = 40
self.otpTextFieldView.separatorSpace = 8
self.otpTextFieldView.shouldAllowIntermediateEditing = false
self.otpTextFieldView.delegate = self
self.otpTextFieldView.initializeUI()
}
```
The `becomeFirstResponderAtIndex` property sets the pinField at the specified index as the first responder.
The `isContentTypeOneTimeCode` property sets the contentType of the first pinField to `.oneTimeCode` to leverage the iOS 12 feature where the passcode is directly fetched from the messages.
#### Styles
```swift
enum DisplayType: Int {
case circular
case roundedCorner
case square
case diamond
case underlinedBottom
}
```
### Delegate Methods
```swift
extension OtpViewController: OTPFieldViewDelegate {
func hasEnteredAllOTP(hasEnteredAll hasEntered: Bool) -> Bool {
print("Has entered all OTP? \(hasEntered)")
return false
}
func shouldBecomeFirstResponderForOTP(otpTextFieldIndex index: Int) -> Bool {
return true
}
func enteredOTP(otp otpString: String) {
print("OTPString: \(otpString)")
}
}
```
- **hasEnteredAllOTP()**: Returns true when all text Fields are full.
- **shouldBecomeFirstResponderForOTP()**: Show keyboard automatically.
- **enteredOTP()**: Get entered pin.
### Properties
- **.displayType**: Display type for Text Field.
- **.fieldsCount**: Length of OTP.
- **.otpInputType**: Input type for Text Field : numeric, alphabet, alphaNumeric.
- **.fieldFont**: Font for Text Field.
- **.secureEntry**: Shows • instead of text.
- **.hideEnteredText**: Hides the text.
- **.requireCursor**: Shows/Hides cursor.
- **.cursorColor**: Color for Cursor.
- **.fieldSize**: Size of Text Field.
- **.separatorSpace**: Space between Text Fields.
- **.fieldBorderWidth**: Border width for Text Fields.
- **.shouldAllowIntermediateEditing**: Allow to edit from middle.
- **.defaultBackgroundColor**: Empty text field background color.
- **.filledBackgroundColor**: Filled text field background color.
- **.defaultBorderColor**: Empty text field border color.
- **.filledBorderColor**: Filled text field border color.
- **.errorBorderColor**: Error text field border color.
- **.delegate**: delegate.
## License
OTPFieldView is available under the MIT license. See LICENSE for details.
gitextract_1c6mpg_h/ ├── LICENSE ├── OTPFieldView/ │ ├── Info.plist │ ├── OTPFieldView.h │ ├── OTPFieldView.swift │ └── OTPTextField.swift ├── OTPFieldView.podspec ├── OTPFieldView.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata/ │ │ └── vaibhavbhasin.xcuserdatad/ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata/ │ └── vaibhavbhasin.xcuserdatad/ │ └── xcschemes/ │ └── xcschememanagement.plist ├── OTPFieldViewTests/ │ ├── Info.plist │ └── OTPFieldViewTests.swift └── README.md
Condensed preview — 14 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (48K chars).
[
{
"path": "LICENSE",
"chars": 1071,
"preview": "MIT License\n\nCopyright (c) 2019 Vaibhav Bhasin\n\nPermission is hereby granted, free of charge, to any person obtaining a "
},
{
"path": "OTPFieldView/Info.plist",
"chars": 728,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "OTPFieldView/OTPFieldView.h",
"chars": 523,
"preview": "//\n// OTPFieldView.h\n// OTPFieldView\n//\n// Created by Vaibhav Bhasin on 10/09/19.\n// Copyright © 2019 Vaibhav Bhasin"
},
{
"path": "OTPFieldView/OTPFieldView.swift",
"chars": 13236,
"preview": "//\n// OTPFieldView.swift\n// OTPFieldView\n//\n// Created by Vaibhav Bhasin on 10/09/19.\n// Copyright © 2019 Vaibhav Bh"
},
{
"path": "OTPFieldView/OTPTextField.swift",
"chars": 4389,
"preview": "//\n// OTPTextField.swift\n// OTPFieldView\n//\n// Created by Vaibhav Bhasin on 10/09/19.\n// Copyright © 2019 Vaibhav Bh"
},
{
"path": "OTPFieldView.podspec",
"chars": 759,
"preview": "Pod::Spec.new do |spec|\n\n spec.name = \"OTPFieldView\"\n spec.version = \"1.0.1\"\n spec.summary = \"A Coc"
},
{
"path": "OTPFieldView.xcodeproj/project.pbxproj",
"chars": 17132,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 50;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "OTPFieldView.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 157,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:OTPFieldView.xc"
},
{
"path": "OTPFieldView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
"chars": 238,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "OTPFieldView.xcodeproj/xcuserdata/vaibhavbhasin.xcuserdatad/xcschemes/xcschememanagement.plist",
"chars": 466,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "OTPFieldViewTests/Info.plist",
"chars": 701,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "OTPFieldViewTests/OTPFieldViewTests.swift",
"chars": 898,
"preview": "//\n// OTPFieldViewTests.swift\n// OTPFieldViewTests\n//\n// Created by Vaibhav Bhasin on 10/09/19.\n// Copyright © 2019 "
},
{
"path": "README.md",
"chars": 3688,
"preview": "# OTPFieldView\nOne Time Password View for iOS. Built in Swift 5\n\n<p align=\"left\">\n<a href=\"https://developer.apple.com/s"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the Root-vb/OTPFieldView GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 14 files (43.0 KB), approximately 12.4k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.