Repository: kirualex/KAPinField Branch: master Commit: 5abe6d3898d6 Files: 25 Total size: 87.1 KB Directory structure: gitextract_s_49u272/ ├── .github/ │ └── FUNDING.yml ├── .gitignore ├── .swift-version ├── .travis.yml ├── KAPinField/ │ ├── Example/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift │ └── Sources/ │ ├── Info.plist │ ├── KAPinField.h │ └── KAPinField.swift ├── KAPinField.podspec ├── KAPinField.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ ├── KAPinField iOS.xcscheme │ └── KAPinField.xcscheme ├── KAPinField.xcworkspace/ │ ├── contents.xcworkspacedata │ └── xcshareddata/ │ └── IDEWorkspaceChecks.plist ├── LICENSE ├── Package.swift └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/FUNDING.yml ================================================ github: [kirualex] custom: ['https://www.paypal.me/alexiscreuzot'] ================================================ FILE: .gitignore ================================================ # Xcode # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore ## Build generated build/ DerivedData/ ## Various settings *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata/ ## Other *.moved-aside *.xccheckout *.xcscmblueprint ## Obj-C/Swift specific *.hmap *.ipa *.dSYM.zip *.dSYM ## Playgrounds timeline.xctimeline playground.xcworkspace # Swift Package Manager # # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. # Packages/ # Package.pins # Package.resolved .build/ # CocoaPods # # We recommend against adding the Pods directory to your .gitignore. However # you should judge for yourself, the pros and cons are mentioned at: # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control # # Pods/ # Carthage # # Add this line if you want to avoid checking in source code from Carthage dependencies. # Carthage/Checkouts Carthage/Build # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the # screenshots whenever they are needed. # For more information about the recommended setup visit: # https://docs.fastlane.tools/best-practices/source-control/#source-control fastlane/report.xml fastlane/Preview.html fastlane/screenshots/**/*.png fastlane/test_output .DS_Store ================================================ FILE: .swift-version ================================================ 5.4 ================================================ FILE: .travis.yml ================================================ language: swift osx_image: xcode10 branches: only: - master script: - xcodebuild build -project KAPinField.xcodeproj -scheme KAPinField -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone X,OS=12' | xcpretty ================================================ FILE: KAPinField/Example/AppDelegate.swift ================================================ // // AppDelegate.swift // KAPinCode // // Created by Alexis Creuzot on 15/10/2018. // Copyright © 2018 alexiscreuzot. All rights reserved. // import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { return true } } ================================================ FILE: KAPinField/Example/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" }, { "idiom" : "ios-marketing", "size" : "1024x1024", "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: KAPinField/Example/Assets.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: KAPinField/Example/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: KAPinField/Example/Base.lproj/Main.storyboard ================================================ ================================================ FILE: KAPinField/Example/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UIStatusBarStyle UIStatusBarStyleLightContent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: KAPinField/Example/ViewController.swift ================================================ // // ViewController.swift // KAPinCode // // Created by Alexis Creuzot on 15/10/2018. // Copyright © 2018 alexiscreuzot. All rights reserved. // import UIKit class ViewController: UIViewController { @IBOutlet var secureSwitch: UISwitch! @IBOutlet var secureLabel: UILabel! @IBOutlet var targetCodeLabel: UILabel! @IBOutlet var pinField: KAPinField! @IBOutlet var refreshButton: UIButton! @IBOutlet var keyboardheightConstraint: NSLayoutConstraint! private var targetCode = "" override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } override func viewDidLoad() { super.viewDidLoad() // -- Properties -- self.setupPinfield() // Get focus pinField.becomeFirstResponder() } func randomCode(numDigits: Int) -> String { var string = "" for _ in 0.. CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType FMWK CFBundleShortVersionString 1.0 CFBundleVersion $(CURRENT_PROJECT_VERSION) ================================================ FILE: KAPinField/Sources/KAPinField.h ================================================ // // KAPinField.h // KAPinField // // Created by Basem Emara on 2019-04-16. // Copyright © 2019 alexiscreuzot. All rights reserved. // #import //! Project version number for KAPinField. FOUNDATION_EXPORT double KAPinFieldVersionNumber; //! Project version string for KAPinField. FOUNDATION_EXPORT const unsigned char KAPinFieldVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import ================================================ FILE: KAPinField/Sources/KAPinField.swift ================================================ // // KAPinField.swift // KAPinCode // // Created by Alexis Creuzot on 15/10/2018. // Copyright © 2018 alexiscreuzot. All rights reserved. // import UIKit // Mark: - KAPinFieldDelegate public protocol KAPinFieldDelegate : AnyObject { func pinField(_ field: KAPinField, didChangeTo string: String, isValid: Bool) // Optional func pinField(_ field: KAPinField, didFinishWith code: String) } public extension KAPinFieldDelegate { func pinField(_ field: KAPinField, didChangeTo string: String, isValid: Bool) {} } public struct KAPinFieldProperties { public weak var delegate : KAPinFieldDelegate? = nil public var numberOfCharacters: Int = 4 { didSet { precondition(numberOfCharacters >= 0, "🚫 Number of character must be >= 0, with 0 meaning dynamic") } } public var validCharacters: String = "0123456789" { didSet { precondition(validCharacters.count > 0, "🚫 There must be at least 1 valid character") precondition(!validCharacters.contains(token), "🚫 Valid characters can't contain token \"\(token)\"") } } public var token: Character = "•" { didSet { precondition(!validCharacters.contains(token), "🚫 token can't be one of the valid characters \"\(token)\"") precondition(!token.isWhitespace, "🚫 token can't be a whitespace. Please use a token with a clear color to achieve the same effect") } } public var animateFocus : Bool = true public var isSecure : Bool = false public var secureToken: Character = "•" public var isUppercased: Bool = false public var keyboardType: UIKeyboardType = .numberPad } public struct KAPinFieldAppearance { public init() {} public var font : KA_MonospacedFont? = .menlo(40) public var tokenColor : UIColor = .black public var tokenFocusColor : UIColor = .gray public var textColor : UIColor = .black public var kerning : CGFloat = 20.0 public var backColor : UIColor = UIColor.clear public var backBorderColor : UIColor = UIColor.clear public var backBorderWidth : CGFloat = 1 public var backCornerRadius : CGFloat = 4 public var backOffset : CGFloat = 4 public var backFocusColor : UIColor = .clear public var backBorderFocusColor : UIColor = .black public var backActiveColor : UIColor = .clear public var backBorderActiveColor : UIColor = .black public var backRounded : Bool = false } // Mark: - KAPinField Class public class KAPinField : UITextField { public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) self.reload() } // Mark: - Public vars private (set) var properties = KAPinFieldProperties() { didSet { self.reload() } } private (set) var appearance = KAPinFieldAppearance() { didSet { self.reloadAppearance() } } public func updateProperties(block : ((inout KAPinFieldProperties) -> ())) { var properties = self.properties block(&properties) self.properties = properties } public func updateAppearence(block : ((inout KAPinFieldAppearance) -> ())) { var appearance = self.appearance block(&appearance) self.appearance = appearance } // Mark: - Overriden vars public override var text : String? { get { return invisibleText } set { self.invisibleField.text = newValue } } public override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { return action == #selector(paste(_:)) // Only allow pasting } // Mark: - Private vars private var isRightToLeft : Bool { return UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft } // Uses an invisible UITextField to handle text // this is necessary for iOS12 .oneTimePassword feature // Remove textField.inputView = UIView() to fix issue with keyboard private var invisibleField: UITextField = { let textField = UITextField() return textField }() private var invisibleText : String { get { return invisibleField.text ?? "" } set { self.reloadAppearance() } } private var attributes: [NSAttributedString.Key : Any] = [:] private var backViews: [UIView] = [UIView]() private var isAnimating: Bool = false private var lastEntry: String = "" private var timer : Timer? private var currentFocusRange : NSRange? private var previousCode : String? private var isDynamicLength = false private var toolbar : UIToolbar? // Mark: - UIKeyInput public override func insertText(_ text: String) { self.invisibleField.insertText(text) } public override func deleteBackward() { self.invisibleField.deleteBackward() } public override var hasText: Bool { return self.invisibleField.hasText } // Mark: - Lifecycle public override var keyboardAppearance: UIKeyboardAppearance { get { return self.invisibleField.keyboardAppearance } set { self.invisibleField.keyboardAppearance = newValue} } public override var keyboardType: UIKeyboardType { get { return self.invisibleField.keyboardType } set { self.invisibleField.keyboardType = newValue} } public override func reloadInputViews() { invisibleField.reloadInputViews() } override public func awakeFromNib() { super.awakeFromNib() self.reload() } override public func layoutSubviews() { super.layoutSubviews() self.bringSubviewToFront(self.invisibleField) self.invisibleField.frame = self.bounds guard !self.isAnimating, !self.isDynamicLength else { return } // back views var myText = "" for _ in 0.. Bool { return self.invisibleField.becomeFirstResponder() } public func animateFailure(_ completion : (() -> Void)? = nil) { guard !self.isAnimating else { return } isAnimating = true CATransaction.begin() CATransaction.setCompletionBlock({ self.isAnimating = false completion?() self.reloadAppearance() }) let animation = CAKeyframeAnimation(keyPath: "transform.translation.x") animation.timingFunction = CAMediaTimingFunction.init(name: .linear) animation.duration = 0.6 animation.values = [-14.0, 14.0, -14.0, 14.0, -8.0, 8.0, -4.0, 4.0, 0.0 ] layer.add(animation, forKey: "shake") CATransaction.commit() } public func animateSuccess(with text: String, completion : (() -> Void)? = nil) { guard !self.isAnimating else { return } self.isAnimating = true UIView.animate(withDuration: 0.2, animations: { for v in self.backViews { v.alpha = 0 } self.transform = CGAffineTransform(scaleX: 0.9, y: 0.9) self.alpha = 0 }) { _ in self.attributedText = NSAttributedString(string: text, attributes: self.attributes) UIView.animate(withDuration: 0.2, animations: { self.transform = CGAffineTransform.identity self.alpha = 1.0 }) { _ in DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { self.isAnimating = false completion?() } } } } // Mark: - Private function @objc func cancelNumberPad() { self.endEditing(true) } @objc func doneWithNumberPad() { self.properties.delegate?.pinField(self, didFinishWith: self.invisibleText) } private func reload() { // Dynamic length flag isDynamicLength = (self.properties.numberOfCharacters == 0) // Only setup if view showing guard self.superview != nil else { return } self.endEditing(true) if isDynamicLength { if self.inputAccessoryView == nil { let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50) let numberToolbar = UIToolbar(frame:frame) numberToolbar.barStyle = .default numberToolbar.items = [ UIBarButtonItem.init(barButtonSystemItem: .cancel, target: self, action: #selector(cancelNumberPad)), UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil), UIBarButtonItem.init(barButtonSystemItem: .done, target: self, action: #selector(doneWithNumberPad)) ] numberToolbar.sizeToFit() self.inputAccessoryView = numberToolbar } } else { self.inputAccessoryView = nil } // Debugging --------------- // Change alpha for easy debug let alpha: CGFloat = 0.0 self.invisibleField.backgroundColor = UIColor.white.withAlphaComponent(alpha * 0.8) self.invisibleField.tintColor = UIColor.black.withAlphaComponent(alpha) self.invisibleField.textColor = UIColor.black.withAlphaComponent(alpha) // -------------------------- // Prepare `invisibleField` self.invisibleField.textAlignment = .center self.invisibleField.autocapitalizationType = .none self.invisibleField.autocorrectionType = .no self.invisibleField.spellCheckingType = .no self.invisibleField.keyboardType = self.properties.keyboardType if #available(iOS 12.0, *) { // Show possible prediction on iOS >= 12 self.invisibleField.textContentType = .oneTimeCode self.invisibleField.autocorrectionType = .yes } self.addSubview(self.invisibleField) self.invisibleField.addTarget(self, action: #selector(reloadAppearance), for: .allEditingEvents) // Prepare visible field self.tintColor = .clear // Hide cursor self.invisibleField.tintColor = .clear // Hide cursor self.contentVerticalAlignment = .center // Set back views for v in self.backViews { v.removeFromSuperview() } self.backViews.removeAll(keepingCapacity: false) for _ in 0.. Bool in return result && self.properties.validCharacters.contains(char) } if text.count <= self.properties.numberOfCharacters { self.properties.delegate?.pinField(self, didChangeTo: text, isValid: isValid) } lastEntry = text } text = String(text.lazy.filter(self.properties.validCharacters.contains)) if !self.isDynamicLength { text = String(text.prefix(self.properties.numberOfCharacters)) } self.invisibleField.text = text } // Always position cursor on last valid character private func updateCursorPosition() { self.currentFocusRange = nil let offset = min(self.invisibleText.count, self.properties.numberOfCharacters) // Only works with a small delay DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { if let position = self.invisibleField.position(from: self.invisibleField.beginningOfDocument, offset: offset) { let textRange = self.textRange(from: position, to: position) self.invisibleField.selectedTextRange = textRange // Compute the currently focused element if let attString = self.attributedText?.mutableCopy() as? NSMutableAttributedString, var range = self.invisibleField.selectedRange, range.location >= -1 && range.location < self.properties.numberOfCharacters { // Compute range of focused text if self.isRightToLeft { range.location = self.properties.numberOfCharacters-range.location-1 } range.length = 1 // Make sure it's a token that is focused let string = attString.string let startIndex = string.index(string.startIndex, offsetBy: range.location) let endIndex = string.index(startIndex, offsetBy: 1) let sub = string[startIndex.. UIFont { switch self { case .courier(let size) : return UIFont(name: "Courier", size: size)! case .courierBold(let size) : return UIFont(name: "Courier-Bold", size: size)! case .courierBoldOblique(let size) : return UIFont(name: "Courier-BoldOblique", size: size)! case .courierOblique(let size) : return UIFont(name: "Courier-Oblique", size: size)! case .courierNewBoldItalic(let size) : return UIFont(name: "CourierNewPS-BoldItalicMT", size: size)! case .courierNewBold(let size) : return UIFont(name: "CourierNewPS-BoldMT", size: size)! case .courierNewItalic(let size) : return UIFont(name: "CourierNewPS-ItalicMT", size: size)! case .courierNew(let size) : return UIFont(name: "CourierNewPSMT", size: size)! case .menloBold(let size) : return UIFont(name: "Menlo-Bold", size: size)! case .menloBoldItalic(let size) : return UIFont(name: "Menlo-BoldItalic", size: size)! case .menloItalic(let size) : return UIFont(name: "Menlo-Italic", size: size)! case .menlo(let size) : return UIFont(name: "Menlo-Regular", size: size)! } } } ================================================ FILE: KAPinField.podspec ================================================ Pod::Spec.new do |s| s.name = 'KAPinField' s.version = '5.0.3' s.summary = 'Lightweight, highly customizable Pin Code Field library for iOS, written in Swift' s.homepage = 'https://github.com/kirualex/KAPinField' s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "Alexis Creuzot" => "alexis.creuzot@gmail.com" } s.source = { :git => "https://github.com/kirualex/KAPinField.git", :tag => s.version.to_s } s.platform = :ios, '9.0' s.source_files = '**/KAPinField.swift' end ================================================ FILE: KAPinField.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 50; objects = { /* Begin PBXBuildFile section */ 8BA8433222667EE000CC8D98 /* KAPinField.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8BA8432B22667EE000CC8D98 /* KAPinField.framework */; }; 8BA8433322667EE000CC8D98 /* KAPinField.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8BA8432B22667EE000CC8D98 /* KAPinField.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 8BA843382266800600CC8D98 /* KAPinField.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BA8432D22667EE000CC8D98 /* KAPinField.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8BA843392266803200CC8D98 /* KAPinField.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAE9C7121749E5200ACE4E6 /* KAPinField.swift */; }; FAAE9C6021749E0200ACE4E6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAE9C5F21749E0200ACE4E6 /* AppDelegate.swift */; }; FAAE9C6221749E0200ACE4E6 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAE9C6121749E0200ACE4E6 /* ViewController.swift */; }; FAAE9C6521749E0200ACE4E6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FAAE9C6321749E0200ACE4E6 /* Main.storyboard */; }; FAAE9C6721749E0300ACE4E6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FAAE9C6621749E0300ACE4E6 /* Assets.xcassets */; }; FAAE9C6A21749E0300ACE4E6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FAAE9C6821749E0300ACE4E6 /* LaunchScreen.storyboard */; }; FAAE9C7221749E5200ACE4E6 /* KAPinField.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAE9C7121749E5200ACE4E6 /* KAPinField.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 8BA8433022667EE000CC8D98 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = FAAE9C5421749E0100ACE4E6 /* Project object */; proxyType = 1; remoteGlobalIDString = 8BA8432A22667EE000CC8D98; remoteInfo = "KAPinField iOS"; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ 8BA8433722667EE000CC8D98 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( 8BA8433322667EE000CC8D98 /* KAPinField.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 8BA8432B22667EE000CC8D98 /* KAPinField.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KAPinField.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8BA8432D22667EE000CC8D98 /* KAPinField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KAPinField.h; sourceTree = ""; }; 8BA8432E22667EE000CC8D98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; FAAE9C5C21749E0100ACE4E6 /* KAPinField.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KAPinField.app; sourceTree = BUILT_PRODUCTS_DIR; }; FAAE9C5F21749E0200ACE4E6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; FAAE9C6121749E0200ACE4E6 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; FAAE9C6421749E0200ACE4E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; FAAE9C6621749E0300ACE4E6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; FAAE9C6921749E0300ACE4E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; FAAE9C6B21749E0300ACE4E6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; FAAE9C7121749E5200ACE4E6 /* KAPinField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KAPinField.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 8BA8432822667EE000CC8D98 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; FAAE9C5921749E0100ACE4E6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 8BA8433222667EE000CC8D98 /* KAPinField.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ FA88CCEC2174FA7C00EFDA17 /* Sources */ = { isa = PBXGroup; children = ( FAAE9C7121749E5200ACE4E6 /* KAPinField.swift */, 8BA8432D22667EE000CC8D98 /* KAPinField.h */, 8BA8432E22667EE000CC8D98 /* Info.plist */, ); path = Sources; sourceTree = ""; }; FA88CCED2174FA8600EFDA17 /* Example */ = { isa = PBXGroup; children = ( FAAE9C5F21749E0200ACE4E6 /* AppDelegate.swift */, FAAE9C6121749E0200ACE4E6 /* ViewController.swift */, FAAE9C6321749E0200ACE4E6 /* Main.storyboard */, FAAE9C6621749E0300ACE4E6 /* Assets.xcassets */, FAAE9C6821749E0300ACE4E6 /* LaunchScreen.storyboard */, FAAE9C6B21749E0300ACE4E6 /* Info.plist */, ); path = Example; sourceTree = ""; }; FAAE9C5321749E0100ACE4E6 = { isa = PBXGroup; children = ( FAAE9C5E21749E0200ACE4E6 /* KAPinField */, FAAE9C5D21749E0100ACE4E6 /* Products */, ); sourceTree = ""; }; FAAE9C5D21749E0100ACE4E6 /* Products */ = { isa = PBXGroup; children = ( FAAE9C5C21749E0100ACE4E6 /* KAPinField.app */, 8BA8432B22667EE000CC8D98 /* KAPinField.framework */, ); name = Products; sourceTree = ""; }; FAAE9C5E21749E0200ACE4E6 /* KAPinField */ = { isa = PBXGroup; children = ( FA88CCEC2174FA7C00EFDA17 /* Sources */, FA88CCED2174FA8600EFDA17 /* Example */, ); path = KAPinField; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 8BA8432622667EE000CC8D98 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 8BA843382266800600CC8D98 /* KAPinField.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 8BA8432A22667EE000CC8D98 /* KAPinField iOS */ = { isa = PBXNativeTarget; buildConfigurationList = 8BA8433622667EE000CC8D98 /* Build configuration list for PBXNativeTarget "KAPinField iOS" */; buildPhases = ( 8BA8432622667EE000CC8D98 /* Headers */, 8BA8432722667EE000CC8D98 /* Sources */, 8BA8432822667EE000CC8D98 /* Frameworks */, 8BA8432922667EE000CC8D98 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "KAPinField iOS"; productName = "KAPinField iOS"; productReference = 8BA8432B22667EE000CC8D98 /* KAPinField.framework */; productType = "com.apple.product-type.framework"; }; FAAE9C5B21749E0100ACE4E6 /* KAPinField */ = { isa = PBXNativeTarget; buildConfigurationList = FAAE9C6E21749E0300ACE4E6 /* Build configuration list for PBXNativeTarget "KAPinField" */; buildPhases = ( FAAE9C5821749E0100ACE4E6 /* Sources */, FAAE9C5921749E0100ACE4E6 /* Frameworks */, FAAE9C5A21749E0100ACE4E6 /* Resources */, 8BA8433722667EE000CC8D98 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( 8BA8433122667EE000CC8D98 /* PBXTargetDependency */, ); name = KAPinField; productName = KAPinCode; productReference = FAAE9C5C21749E0100ACE4E6 /* KAPinField.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ FAAE9C5421749E0100ACE4E6 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1000; LastUpgradeCheck = 1200; ORGANIZATIONNAME = alexiscreuzot; TargetAttributes = { 8BA8432A22667EE000CC8D98 = { CreatedOnToolsVersion = 10.2; }; FAAE9C5B21749E0100ACE4E6 = { CreatedOnToolsVersion = 10.0; LastSwiftMigration = 1020; }; }; }; buildConfigurationList = FAAE9C5721749E0100ACE4E6 /* Build configuration list for PBXProject "KAPinField" */; compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = FAAE9C5321749E0100ACE4E6; productRefGroup = FAAE9C5D21749E0100ACE4E6 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( FAAE9C5B21749E0100ACE4E6 /* KAPinField */, 8BA8432A22667EE000CC8D98 /* KAPinField iOS */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 8BA8432922667EE000CC8D98 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; FAAE9C5A21749E0100ACE4E6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( FAAE9C6A21749E0300ACE4E6 /* LaunchScreen.storyboard in Resources */, FAAE9C6721749E0300ACE4E6 /* Assets.xcassets in Resources */, FAAE9C6521749E0200ACE4E6 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 8BA8432722667EE000CC8D98 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 8BA843392266803200CC8D98 /* KAPinField.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; FAAE9C5821749E0100ACE4E6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( FAAE9C6221749E0200ACE4E6 /* ViewController.swift in Sources */, FAAE9C7221749E5200ACE4E6 /* KAPinField.swift in Sources */, FAAE9C6021749E0200ACE4E6 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 8BA8433122667EE000CC8D98 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 8BA8432A22667EE000CC8D98 /* KAPinField iOS */; targetProxy = 8BA8433022667EE000CC8D98 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ FAAE9C6321749E0200ACE4E6 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( FAAE9C6421749E0200ACE4E6 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; FAAE9C6821749E0300ACE4E6 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( FAAE9C6921749E0300ACE4E6 /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 8BA8433422667EE000CC8D98 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = KAPinField/Sources/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = "com.alexiscreuzot.KAPinField-iOS"; PRODUCT_NAME = KAPinField; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 8BA8433522667EE000CC8D98 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = KAPinField/Sources/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", "@loader_path/Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = "com.alexiscreuzot.KAPinField-iOS"; PRODUCT_NAME = KAPinField; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; FAAE9C6C21749E0300ACE4E6 /* 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 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; 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 = 13.0; 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"; SWIFT_VERSION = 4.2; }; name = Debug; }; FAAE9C6D21749E0300ACE4E6 /* 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 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; 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 = 13.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 4.2; VALIDATE_PRODUCT = YES; }; name = Release; }; FAAE9C6F21749E0300ACE4E6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = J6US63N7X8; INFOPLIST_FILE = "$(SRCROOT)/KAPinField/Example/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = com.alexiscreuzot.KAPinField; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; FAAE9C7021749E0300ACE4E6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = J6US63N7X8; INFOPLIST_FILE = "$(SRCROOT)/KAPinField/Example/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = com.alexiscreuzot.KAPinField; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 8BA8433622667EE000CC8D98 /* Build configuration list for PBXNativeTarget "KAPinField iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 8BA8433422667EE000CC8D98 /* Debug */, 8BA8433522667EE000CC8D98 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; FAAE9C5721749E0100ACE4E6 /* Build configuration list for PBXProject "KAPinField" */ = { isa = XCConfigurationList; buildConfigurations = ( FAAE9C6C21749E0300ACE4E6 /* Debug */, FAAE9C6D21749E0300ACE4E6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; FAAE9C6E21749E0300ACE4E6 /* Build configuration list for PBXNativeTarget "KAPinField" */ = { isa = XCConfigurationList; buildConfigurations = ( FAAE9C6F21749E0300ACE4E6 /* Debug */, FAAE9C7021749E0300ACE4E6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = FAAE9C5421749E0100ACE4E6 /* Project object */; } ================================================ FILE: KAPinField.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: KAPinField.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: KAPinField.xcodeproj/xcshareddata/xcschemes/KAPinField iOS.xcscheme ================================================ ================================================ FILE: KAPinField.xcodeproj/xcshareddata/xcschemes/KAPinField.xcscheme ================================================ ================================================ FILE: KAPinField.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: KAPinField.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 Alexis Creuzot 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: Package.swift ================================================ // swift-tools-version:5.4 import PackageDescription let package = Package( name: "KAPinField", platforms: [ .iOS(.v9), ], products: [ .library( name: "KAPinField", targets: ["KAPinField"] ), ], dependencies: [], targets: [ .target( name: "KAPinField", path: "KAPinField", exclude: [ "Example", "Sources/Info.plist", "Sources/KAPinField.h", ], sources: [ "Sources", ], linkerSettings: [ .linkedFramework("UIKit"), ] ), ] ) ================================================ FILE: README.md ================================================ [![Platform](https://img.shields.io/cocoapods/p/KAPinField.svg?style=flat)](https://alamofire.github.io/KAPinField) [![Language](https://img.shields.io/badge/swift-5.0-blue.svg)](http://swift.org) [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/KAPinField.svg)](https://img.shields.io/cocoapods/v/KAPinField.svg) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-blue.svg?style=flat)](https://github.com/Carthage/Carthage) [![Build Status](https://travis-ci.org/kirualex/KAPinField.svg?branch=master)](https://travis-ci.org/kirualex/KAPinField) [![Pod License](http://img.shields.io/cocoapods/l/SDWebImage.svg?style=flat)](https://raw.githubusercontent.com/kirualex/SwiftyGif/master/LICENSE) # KAPinField ### Lightweight pin code field library for iOS, written in Swift **Supports one time password autofill out of the box !**
Example
## Install With Cocoapods `pod 'KAPinField'` ## Usage ```swift import KAPinField class MyController : UIVIewController { ... } ``` ### Storyboard You can add an UITextField directly in your Storyboard scene and declare it as `KAPinField`. It will automagically become a pin field. You can then customize it from the inspector view to suit your needs. ### Delegation Don't forget to set the delegate likeso : ```swift @IBOutlet var pinField: KAPinField! override func viewDidLoad() { super.viewDidLoad() properties.delegate = self ... } ``` One simple method will be called on your delegate ```swift extension MyController : KAPinFieldDelegate { func pinField(_ field: KAPinField, didFinishWith code: String) { print("didFinishWith : \(code)") } } ``` ### Properties All the logic properties are available in the `KAPinFieldProperties` struct named `properties`. **Token can't be a whitespace due to Apple handling of trailing spaces. You can achieve the same effect using any token with `tokenColor` and `tokenFocusColor` set to `.clear`** ##### Logic ```swift pinField.updateProperties { properties in properties.token = "-" // Default to "•", can't be a whitespace ! properties.numberOfCharacters = 5 // Default to 4 properties.validCharacters = "0123456789+#?" // Default to only numbers, "0123456789" properties.text = "123" // You can set part or all of the text properties.animateFocus = true // Animate the currently focused token properties.isSecure = false // Secure pinField will hide actual input properties.secureToken = "*" // Token used to hide actual character input when using isSecure = true properties.isUppercased = false // You can set this to convert input to uppercased. } ``` ##### Styling All the styling can be done via the `KAPinFieldAppearance` struct named `appearance`. ```swift pinField.updateAppearence { appearance in appearance.font = .menloBold(40) // Default to appearance.MonospacedFont.menlo(40) appearance.kerning = 20 // Space between characters, default to 16 appearance.textColor = UIColor.white.withAlphaComponent(1.0) // Default to nib color or black if initialized programmatically. appearance.tokenColor = UIColor.black.withAlphaComponent(0.3) // token color, default to text color appearance.tokenFocusColor = UIColor.black.withAlphaComponent(0.3) // token focus color, default to token color appearance.backOffset = 8 // Backviews spacing between each other appearance.backColor = UIColor.clear appearance.backBorderWidth = 1 appearance.backBorderColor = UIColor.white.withAlphaComponent(0.2) appearance.backCornerRadius = 4 appearance.backFocusColor = UIColor.clear appearance.backBorderFocusColor = UIColor.white.withAlphaComponent(0.8) appearance.backActiveColor = UIColor.clear appearance.backBorderActiveColor = UIColor.white appearance.keyboardType = UIKeyboardType.numberPad // Specify keyboard type } ``` ### Font A [monospaced font](https://en.wikipedia.org/wiki/Monospaced_font) is highly recommended in order to avoid horizontal offsetting during typing. For this purpose, a handy helper is available to allow you to access native iOS monospaced fonts. To use it, just set `appearance.font` with a enum value from `appearance.MonospacedFont`. You can of course still use your own font by setting the default `font` property on KAPinField. ### Animation `KAPinField` also provide some eye-candy for failure and success. ##### Success ```swift pinfield.animateSuccess(with: "👍") { print("Success") } ``` ##### Failure ```swift pinfield.animateFailure() { print("Failure") } ```