Full Code of kirualex/KAPinField for AI

master 5abe6d3898d6 cached
25 files
87.1 KB
23.8k tokens
1 requests
Download .txt
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
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="KAPinField" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="qkF-b8-Iix">
                                <rect key="frame" x="0.0" y="233.5" width="375" height="50"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="50" id="YgO-D9-lom"/>
                                </constraints>
                                <color key="textColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <fontDescription key="fontDescription" type="system" pointSize="30"/>
                                <textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="numberPad" textContentType="one-time-code"/>
                            </textField>
                            <button opaque="NO" alpha="0.29999999999999999" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fJq-4G-zMg">
                                <rect key="frame" x="140" y="323.5" width="95" height="40"/>
                                <color key="backgroundColor" white="1" alpha="0.14506635270000001" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                <inset key="contentEdgeInsets" minX="10" minY="10" maxX="10" maxY="10"/>
                                <state key="normal" title="Refresh ↻"/>
                            </button>
                        </subviews>
                        <color key="backgroundColor" red="0.094117647060000004" green="0.5450980392" blue="0.96078431369999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="fJq-4G-zMg" firstAttribute="top" secondItem="qkF-b8-Iix" secondAttribute="bottom" constant="40" id="Coz-RY-dac"/>
                            <constraint firstItem="fJq-4G-zMg" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" id="L6C-vl-0Al"/>
                            <constraint firstItem="qkF-b8-Iix" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="PDL-pK-Rme"/>
                            <constraint firstItem="qkF-b8-Iix" firstAttribute="width" secondItem="Ze5-6b-2t3" secondAttribute="width" id="hcw-WT-swN"/>
                            <constraint firstItem="fJq-4G-zMg" firstAttribute="centerX" secondItem="qkF-b8-Iix" secondAttribute="centerX" id="vLW-qI-AWA"/>
                        </constraints>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
</document>


================================================
FILE: KAPinField/Example/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <device id="retina4_0" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="KAPinField" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="u2o-qm-AuS">
                                <rect key="frame" x="0.0" y="0.0" width="320" height="95"/>
                                <subviews>
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="inm-x7-8p7">
                                        <rect key="frame" x="83.5" y="40" width="153" height="31"/>
                                        <subviews>
                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="1000" verticalHuggingPriority="1000" horizontalCompressionResistancePriority="1000" verticalCompressionResistancePriority="1000" text="Secure entry" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pkg-a2-BMf">
                                                <rect key="frame" x="0.0" y="5" width="98" height="21"/>
                                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                <nil key="highlightedColor"/>
                                            </label>
                                            <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="SFt-BM-ZkA">
                                                <rect key="frame" x="106" y="0.0" width="51" height="31"/>
                                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                <color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                <color key="onTintColor" red="0.094117647060000004" green="0.5450980392" blue="0.96078431369999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <color key="thumbTintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                <connections>
                                                    <action selector="toggleSecure" destination="BYZ-38-t0r" eventType="valueChanged" id="ptC-yn-G11"/>
                                                </connections>
                                            </switch>
                                        </subviews>
                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                        <constraints>
                                            <constraint firstAttribute="height" constant="31" id="0Vq-Td-mfx"/>
                                            <constraint firstItem="SFt-BM-ZkA" firstAttribute="top" secondItem="inm-x7-8p7" secondAttribute="top" id="99g-J2-SLZ"/>
                                            <constraint firstAttribute="trailing" secondItem="SFt-BM-ZkA" secondAttribute="trailing" constant="-2" id="Ghh-f8-aoD"/>
                                            <constraint firstItem="pkg-a2-BMf" firstAttribute="leading" secondItem="inm-x7-8p7" secondAttribute="leading" id="cpV-H8-fHf"/>
                                            <constraint firstAttribute="bottom" secondItem="SFt-BM-ZkA" secondAttribute="bottom" id="fd2-2u-ivP"/>
                                            <constraint firstItem="pkg-a2-BMf" firstAttribute="centerY" secondItem="inm-x7-8p7" secondAttribute="centerY" id="tLS-Ub-ZNf"/>
                                            <constraint firstItem="SFt-BM-ZkA" firstAttribute="leading" secondItem="pkg-a2-BMf" secondAttribute="trailing" constant="8" id="z8s-4u-VDZ"/>
                                        </constraints>
                                    </view>
                                </subviews>
                                <viewLayoutGuide key="safeArea" id="4wk-QL-KCj"/>
                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <constraints>
                                    <constraint firstAttribute="bottomMargin" secondItem="inm-x7-8p7" secondAttribute="bottom" constant="16" id="1aP-Ys-tyt"/>
                                    <constraint firstItem="inm-x7-8p7" firstAttribute="top" secondItem="4wk-QL-KCj" secondAttribute="top" constant="40" id="eeH-0k-P4d"/>
                                    <constraint firstItem="inm-x7-8p7" firstAttribute="centerX" secondItem="4wk-QL-KCj" secondAttribute="centerX" id="gdi-hQ-kq3"/>
                                </constraints>
                            </view>
                            <label opaque="NO" alpha="0.5" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" text="Code : 1234" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ee6-G1-KAi">
                                <rect key="frame" x="121" y="145" width="78" height="17"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="17" id="xM1-qL-uy3"/>
                                </constraints>
                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                <nil key="highlightedColor"/>
                            </label>
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZrA-JK-GPg" userLabel="embedViewTest">
                                <rect key="frame" x="0.0" y="182" width="320" height="50"/>
                                <subviews>
                                    <textField opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="250" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="KAPinField" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="d8l-Ws-A8U" customClass="KAPinField" customModule="KAPinField" customModuleProvider="target">
                                        <rect key="frame" x="18" y="0.0" width="284" height="50"/>
                                        <constraints>
                                            <constraint firstAttribute="height" constant="50" id="yDT-nY-Afy"/>
                                        </constraints>
                                        <fontDescription key="fontDescription" type="system" pointSize="30"/>
                                        <textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="numberPad" keyboardAppearance="alert" returnKeyType="go" textContentType="one-time-code"/>
                                    </textField>
                                </subviews>
                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <constraints>
                                    <constraint firstItem="d8l-Ws-A8U" firstAttribute="height" secondItem="ZrA-JK-GPg" secondAttribute="height" id="Af7-la-H6n"/>
                                    <constraint firstItem="d8l-Ws-A8U" firstAttribute="width" secondItem="ZrA-JK-GPg" secondAttribute="width" multiplier="2:3" constant="71" id="W43-aS-BYW"/>
                                    <constraint firstItem="d8l-Ws-A8U" firstAttribute="centerY" secondItem="ZrA-JK-GPg" secondAttribute="centerY" id="Y3y-Ml-fIE"/>
                                    <constraint firstItem="d8l-Ws-A8U" firstAttribute="centerX" secondItem="ZrA-JK-GPg" secondAttribute="centerX" id="zhr-Ur-ONO"/>
                                </constraints>
                            </view>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="deI-wI-pgE">
                                <rect key="frame" x="92" y="264" width="136" height="40"/>
                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="40" id="o02-23-GNN"/>
                                </constraints>
                                <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                <inset key="contentEdgeInsets" minX="10" minY="10" maxX="10" maxY="10"/>
                                <state key="normal" title="Refresh Code ↻">
                                    <color key="titleColor" systemColor="systemBlueColor"/>
                                </state>
                                <connections>
                                    <action selector="setupPinfield" destination="BYZ-38-t0r" eventType="touchUpInside" id="q70-6w-eig"/>
                                </connections>
                            </button>
                        </subviews>
                        <viewLayoutGuide key="safeArea" id="aDb-oH-ANJ"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                        <constraints>
                            <constraint firstItem="deI-wI-pgE" firstAttribute="top" secondItem="ZrA-JK-GPg" secondAttribute="bottom" constant="32" id="7CR-QR-oP5"/>
                            <constraint firstItem="deI-wI-pgE" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="8PS-0h-axA"/>
                            <constraint firstItem="Ee6-G1-KAi" firstAttribute="centerX" secondItem="aDb-oH-ANJ" secondAttribute="centerX" id="8wt-lz-a2B"/>
                            <constraint firstItem="aDb-oH-ANJ" firstAttribute="top" secondItem="u2o-qm-AuS" secondAttribute="top" id="9ha-nD-VAo"/>
                            <constraint firstItem="ZrA-JK-GPg" firstAttribute="width" secondItem="8bC-Xf-vdC" secondAttribute="width" id="BpT-uC-Rgm"/>
                            <constraint firstItem="ZrA-JK-GPg" firstAttribute="centerX" secondItem="aDb-oH-ANJ" secondAttribute="centerX" id="FZP-4I-B0A"/>
                            <constraint firstItem="u2o-qm-AuS" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="Ndg-Hs-4mw"/>
                            <constraint firstAttribute="trailing" secondItem="u2o-qm-AuS" secondAttribute="trailing" id="S0N-eT-0wG"/>
                            <constraint firstItem="ZrA-JK-GPg" firstAttribute="top" secondItem="Ee6-G1-KAi" secondAttribute="bottom" constant="20" id="in4-IT-LYe"/>
                            <constraint firstItem="Ee6-G1-KAi" firstAttribute="top" relation="greaterThanOrEqual" secondItem="u2o-qm-AuS" secondAttribute="bottom" constant="16" id="p0N-xu-6Zl"/>
                            <constraint firstItem="Ee6-G1-KAi" firstAttribute="top" secondItem="u2o-qm-AuS" secondAttribute="bottom" priority="250" constant="40" id="sdr-hB-WxV"/>
                            <constraint firstItem="deI-wI-pgE" firstAttribute="centerY" secondItem="aDb-oH-ANJ" secondAttribute="centerY" priority="751" id="wMO-13-RHJ"/>
                        </constraints>
                    </view>
                    <connections>
                        <outlet property="pinField" destination="d8l-Ws-A8U" id="Hgh-qB-l0c"/>
                        <outlet property="refreshButton" destination="deI-wI-pgE" id="lOe-N8-CAg"/>
                        <outlet property="secureLabel" destination="pkg-a2-BMf" id="4tP-wM-q2f"/>
                        <outlet property="secureSwitch" destination="SFt-BM-ZkA" id="CsQ-xS-7aZ"/>
                        <outlet property="targetCodeLabel" destination="Ee6-G1-KAi" id="1WI-Bj-zMW"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="-42" y="113"/>
        </scene>
    </scenes>
    <resources>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
        <systemColor name="systemBlueColor">
            <color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
        </systemColor>
    </resources>
</document>


================================================
FILE: KAPinField/Example/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>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UIStatusBarStyle</key>
	<string>UIStatusBarStyleLightContent</string>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
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..<numDigits {
            string += String(Int.random(in: 0...9))
        }
        return string
    }
    
    @IBAction func setupPinfield() {
        
        // Random numberOfCharacters
        pinField.text = ""
        
        pinField.updateProperties { properties in
            properties.numberOfCharacters = [4,5].randomElement()!
            properties.delegate = self
        }
        
        // Random target code
        targetCode = self.randomCode(numDigits: pinField.properties.numberOfCharacters)
        targetCodeLabel.text = "Code : \(targetCode)"
        UIPasteboard.general.string = targetCode
        
        self.refresh()
    }
    
    @IBAction func toggleSecure() {
        self.refresh()
        self.pinField.becomeFirstResponder()
    }
    
    func refresh() {
                
        self.targetCodeLabel.textColor = UIColor.label.withAlphaComponent(0.8)
        
        pinField.updateProperties { properties in
            properties.isSecure = self.secureSwitch.isOn
            properties.token = "•"
            properties.animateFocus = false
            properties.isUppercased = false
            properties.validCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
        }
        
        pinField.updateAppearence { appearance in
            appearance.tokenColor = UIColor.clear
            appearance.tokenFocusColor = UIColor.clear
            appearance.textColor = UIColor.label
            appearance.font = .menlo(40)
            appearance.kerning = 24
            appearance.backOffset = 8
            appearance.backColor = UIColor.clear
            appearance.backBorderWidth = 1
            appearance.backBorderColor = UIColor.label.withAlphaComponent(0.2)
            appearance.backCornerRadius = 4
            appearance.backFocusColor = UIColor.clear
            appearance.backBorderFocusColor = UIColor.systemBlue
            appearance.backActiveColor = UIColor.clear
            appearance.backBorderActiveColor = UIColor.label
            appearance.backRounded = false
        }
    }
}

// Mark: - KAPinFieldDelegate
extension ViewController : KAPinFieldDelegate {
    func pinField(_ field: KAPinField, didChangeTo string: String, isValid: Bool) {
        if isValid {
            print("Valid input: \(string) ")
        } else {
            print("Invalid input: \(string) ")
            self.pinField.animateFailure()
        }
    }
    
    func pinField(_ field: KAPinField, didFinishWith code: String) {
        print("didFinishWith : \(code)")
        
        // Randomly show success or failure
        if code != targetCode {
            print("Failure")
            field.animateFailure()
        } else {
            print("Success")
            field.animateSuccess(with: "👍") {
                self.setupPinfield()
            }
            
        }
    }
}



================================================
FILE: KAPinField/Sources/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</string>
	<key>CFBundleVersion</key>
	<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>


================================================
FILE: KAPinField/Sources/KAPinField.h
================================================
//
//  KAPinField.h
//  KAPinField
//
//  Created by Basem Emara on 2019-04-16.
//  Copyright © 2019 alexiscreuzot. All rights reserved.
//

#import <UIKit/UIKit.h>

//! 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 <KAPinField/PublicHeader.h>




================================================
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..<self.properties.numberOfCharacters {
            myText += "0"
        }
        let nsText = NSString(string: myText)
        let textFrame = nsText.boundingRect(with: self.bounds.size,
                                            options: .usesLineFragmentOrigin,
                                            attributes: self.attributes,
                                            context: nil)
        
        
        let actualWidth = textFrame.width
            + (self.appearance.kerning * CGFloat(self.properties.numberOfCharacters))
        let digitWidth = actualWidth / CGFloat(self.properties.numberOfCharacters)
        
        let offset = (self.bounds.width - actualWidth) / 2
        
        for (index, v) in self.backViews.enumerated() {
            let x = CGFloat(index) * digitWidth + offset
            var vFrame = CGRect(x: x,
                                y: -1,
                                width: digitWidth,
                                height: self.bounds.height)
            vFrame.origin.x += self.appearance.backOffset / 2
            vFrame.size.width -= self.appearance.backOffset
            
            if self.appearance.backRounded {
                
                if vFrame.size.height < vFrame.size.width {
                    let delta = vFrame.size.width - vFrame.size.height
                    vFrame.origin.x += delta/2
                } else {
                    let delta = vFrame.size.height - vFrame.size.width
                    vFrame.origin.y += delta/2
                }
                
                let minSide = min(vFrame.size.height, vFrame.size.width)
                vFrame.size.width = minSide
                vFrame.size.height = minSide
                v.layer.cornerRadius = minSide/2
            }
            
            v.frame = vFrame
        }
    }
    
    // Mark: - Public functions
    
    @discardableResult override public func becomeFirstResponder() -> 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..<self.properties.numberOfCharacters {
            let v = UIView()
            backViews.append(v)
            self.addSubview(v)
            self.sendSubviewToBack(v)
        }
        
        // Delay fixes kerning offset issue
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
            self.reloadAppearance()
        }
        
        // Focus token animation
        if self.properties.animateFocus {
            if self.timer == nil {
                self.timer = Timer.scheduledTimer(timeInterval:  0.6, target: self, selector: #selector(animateFocusedToken), userInfo: nil, repeats: true)
                self.timer?.fire()
            }
        } else {
            self.timer?.invalidate()
            self.timer = nil
        }
    }
    
    @objc private func animateFocusedToken() {
        
        guard !isDynamicLength else {
            return
        }
        
        if  let attString = self.attributedText?.mutableCopy() as? NSMutableAttributedString,
            let range = self.currentFocusRange {
            
            var atts = attString.attributes(at: range.location, effectiveRange: nil)
            
            guard let color = atts[.foregroundColor] as? UIColor else {
                return
            }
            let isClear = (color == .clear)
            let duration: Double = isClear ? 0.3 : 0.6
            if isClear{
                atts[.foregroundColor] = self.appearance.tokenFocusColor
            } else {
                atts[.foregroundColor] = UIColor.clear
            }
            attString.setAttributes(atts, range: range)
            
            UIView.transition(with: self, duration: duration, options: [.transitionCrossDissolve, .allowUserInteraction], animations: {
                self.attributedText = attString
            }, completion: nil)
            
        }
    }
    
    // Updates textfield content
    @objc public func reloadAppearance() {
        
        guard !self.isAnimating else {
            return
        }
        
        // Styling backviews
        for v in self.backViews {
            v.alpha = 1.0
            v.backgroundColor = self.appearance.backColor
            v.layer.borderColor = self.appearance.backBorderColor.cgColor
            v.layer.borderWidth = self.appearance.backBorderWidth
            v.layer.cornerRadius = self.appearance.backCornerRadius
        }
        
        self.sanitizeText()
        
        let paragraph = NSMutableParagraphStyle()
        paragraph.alignment = .center
        
        let font =  self.appearance.font?.font() ?? self.font ?? UIFont.preferredFont(forTextStyle: .headline)
        self.attributes = [ .paragraphStyle : paragraph,
                            .font : font,
                            .kern : self.appearance.kerning]
        
        if isDynamicLength {
            attributes[.foregroundColor] = self.appearance.textColor
            self.attributedText =  NSAttributedString(string: self.invisibleField.text!, attributes: attributes)
            return
        }
        
        // Display
        let attString = NSMutableAttributedString(string: "")
        let loopStride = isRightToLeft
            ? stride(from: self.properties.numberOfCharacters-1, to: -1, by: -1)
            : stride(from: 0, to: self.properties.numberOfCharacters, by: 1)
        
        for i in loopStride {
            
            var string = ""
            var isToken = false
            if i < invisibleText.count {
                if self.properties.isSecure {
                    string = String(self.properties.secureToken)
                } else {
                    let index = invisibleText.index(string.startIndex, offsetBy: i)
                    string = String(invisibleText[index])
                }
                
            } else {
                isToken = true
                string = String(self.properties.token)
            }
            
            // Color for active / inactive
            let backIndex = self.isRightToLeft ? self.properties.numberOfCharacters-i-1 : i
            if !self.backViews.isEmpty && backIndex < self.backViews.count {
                let backView = self.backViews[backIndex]
                if isToken {
                    attributes[.foregroundColor] = self.appearance.tokenColor
                    backView.backgroundColor = self.appearance.backColor
                    backView.layer.borderColor = self.appearance.backBorderColor.cgColor
                } else {
                    attributes[.foregroundColor] = self.appearance.textColor
                    backView.backgroundColor = self.appearance.backActiveColor
                    backView.layer.borderColor = self.appearance.backBorderActiveColor.cgColor
                }
            }

            // Fix kerning-centering
            let indexForKernFix = isRightToLeft ? 0 : self.properties.numberOfCharacters-1
            if i == indexForKernFix {
                attributes[.kern] = 0.0
            }
            
            attString.append(NSAttributedString(string: string, attributes: attributes))
        }
        
        if #available(iOS 11.0, *) {
            self.updateCursorPosition()
        }
        
        guard !self.isAnimating else {
            return
        }
        
        self.attributedText = attString
        
        if invisibleText == self.previousCode {
            return
        }
        self.previousCode = invisibleText
        
        //        self.sizeToFit()
        self.checkCodeValidity()
    }
    
    private func sanitizeText() {
        var text = self.invisibleField.text ?? ""
        
        if properties.isUppercased {
            text = text.uppercased()
        }
        
        if text != lastEntry {
            let isValid = text.reduce(true) { result, char -> 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..<endIndex]
                    if sub == String(self.properties.token) {
                        
                        // Token focus color
                        var atts = attString.attributes(at: range.location, effectiveRange: nil)
                        atts[.foregroundColor] = self.appearance.tokenFocusColor
                        attString.setAttributes(atts, range: range)
                        
                        // Avoid long fade from tick()
                        UIView.transition(with: self, duration: 0.1, options: [.transitionCrossDissolve, .allowUserInteraction], animations: {
                            self.attributedText = attString
                        }, completion: nil)
                        
                        self.currentFocusRange = range
                        
                        // Backview focus color
                        var backIndex = self.isRightToLeft ? self.properties.numberOfCharacters-offset-1 : offset
                        backIndex = min(backIndex, self.properties.numberOfCharacters-1)
                        backIndex = max(backIndex, 0)
                        if !self.backViews.isEmpty && backIndex < self.backViews.count {
                            let backView = self.backViews[backIndex]
                            backView.backgroundColor = self.appearance.backFocusColor
                            backView.layer.borderColor = self.appearance.backBorderFocusColor.cgColor
                        }
                    }
                }
            }
        }
    }
    
    private func checkCodeValidity() {
        
        guard !self.isAnimating, !self.isDynamicLength else {
            return
        }
        
        if self.invisibleText.count == self.properties.numberOfCharacters {
            if let pinDelegate = self.properties.delegate {
                let result = isRightToLeft ? String(self.invisibleText.reversed()) : self.invisibleText
                pinDelegate.pinField(self, didFinishWith: result)
            } else {
                print("⚠️ : No delegate set for KAPinField. Set it via yourPinField.properties.delegate.")
            }
        }
    }
}

private extension UITextInput {
    var selectedRange: NSRange? {
        guard let range = selectedTextRange else { return nil }
        let location = offset(from: beginningOfDocument, to: range.start)
        let length = offset(from: range.start, to: range.end)
        return NSRange(location: location, length: length)
    }
}

// Mark: - KA_MonospacedFont
// Helper to provide monospaced fonts via literal
public enum KA_MonospacedFont {
    
    case courier(CGFloat)
    case courierBold(CGFloat)
    case courierBoldOblique(CGFloat)
    case courierOblique(CGFloat)
    case courierNewBoldItalic(CGFloat)
    case courierNewBold(CGFloat)
    case courierNewItalic(CGFloat)
    case courierNew(CGFloat)
    case menloBold(CGFloat)
    case menloBoldItalic(CGFloat)
    case menloItalic(CGFloat)
    case menlo(CGFloat)
    
    func font() -> 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 = "<group>"; };
		8BA8432E22667EE000CC8D98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		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 = "<group>"; };
		FAAE9C6121749E0200ACE4E6 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
		FAAE9C6421749E0200ACE4E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
		FAAE9C6621749E0300ACE4E6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		FAAE9C6921749E0300ACE4E6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		FAAE9C6B21749E0300ACE4E6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		FAAE9C7121749E5200ACE4E6 /* KAPinField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KAPinField.swift; sourceTree = "<group>"; };
/* 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 = "<group>";
		};
		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 = "<group>";
		};
		FAAE9C5321749E0100ACE4E6 = {
			isa = PBXGroup;
			children = (
				FAAE9C5E21749E0200ACE4E6 /* KAPinField */,
				FAAE9C5D21749E0100ACE4E6 /* Products */,
			);
			sourceTree = "<group>";
		};
		FAAE9C5D21749E0100ACE4E6 /* Products */ = {
			isa = PBXGroup;
			children = (
				FAAE9C5C21749E0100ACE4E6 /* KAPinField.app */,
				8BA8432B22667EE000CC8D98 /* KAPinField.framework */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		FAAE9C5E21749E0200ACE4E6 /* KAPinField */ = {
			isa = PBXGroup;
			children = (
				FA88CCEC2174FA7C00EFDA17 /* Sources */,
				FA88CCED2174FA8600EFDA17 /* Example */,
			);
			path = KAPinField;
			sourceTree = "<group>";
		};
/* 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 = "<group>";
		};
		FAAE9C6821749E0300ACE4E6 /* LaunchScreen.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				FAAE9C6921749E0300ACE4E6 /* Base */,
			);
			name = LaunchScreen.storyboard;
			sourceTree = "<group>";
		};
/* 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
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:/Users/alex/Development/iOS/_frameworks/KAPinCode/KAPinField.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: KAPinField.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: KAPinField.xcodeproj/xcshareddata/xcschemes/KAPinField iOS.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "1200"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "8BA8432A22667EE000CC8D98"
               BuildableName = "KAPinField.framework"
               BlueprintName = "KAPinField iOS"
               ReferencedContainer = "container:KAPinField.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <Testables>
      </Testables>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "8BA8432A22667EE000CC8D98"
            BuildableName = "KAPinField.framework"
            BlueprintName = "KAPinField iOS"
            ReferencedContainer = "container:KAPinField.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "8BA8432A22667EE000CC8D98"
            BuildableName = "KAPinField.framework"
            BlueprintName = "KAPinField iOS"
            ReferencedContainer = "container:KAPinField.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: KAPinField.xcodeproj/xcshareddata/xcschemes/KAPinField.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "1200"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "FAAE9C5B21749E0100ACE4E6"
               BuildableName = "KAPinField.app"
               BlueprintName = "KAPinField"
               ReferencedContainer = "container:KAPinField.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "FAAE9C5B21749E0100ACE4E6"
            BuildableName = "KAPinField.app"
            BlueprintName = "KAPinField"
            ReferencedContainer = "container:KAPinField.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <Testables>
      </Testables>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "FAAE9C5B21749E0100ACE4E6"
            BuildableName = "KAPinField.app"
            BlueprintName = "KAPinField"
            ReferencedContainer = "container:KAPinField.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "FAAE9C5B21749E0100ACE4E6"
            BuildableName = "KAPinField.app"
            BlueprintName = "KAPinField"
            ReferencedContainer = "container:KAPinField.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: KAPinField.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "container:KAPinField.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: KAPinField.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: 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 !**

<table>
  <tr>
    <td>
      <img src="https://github.com/kirualex/KAPinField/blob/4.0.0/preview1.gif"  width="400"  />
    </td>
  </tr>
  <tr>
  <td align=center>
      Example
    </td>
   </tr>
 </table>

## 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")
}
```
Download .txt
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
Condensed preview — 25 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (97K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 67,
    "preview": "github: [kirualex]\ncustom: ['https://www.paypal.me/alexiscreuzot']\n"
  },
  {
    "path": ".gitignore",
    "chars": 1486,
    "preview": "# Xcode\n#\n# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore\n\n"
  },
  {
    "path": ".swift-version",
    "chars": 4,
    "preview": "5.4\n"
  },
  {
    "path": ".travis.yml",
    "chars": 231,
    "preview": "language: swift\nosx_image: xcode10\n\nbranches:\n only:\n - master\n\nscript:\n - xcodebuild build -project KAPinField.xcodepro"
  },
  {
    "path": "KAPinField/Example/AppDelegate.swift",
    "chars": 441,
    "preview": "//\n//  AppDelegate.swift\n//  KAPinCode\n//\n//  Created by Alexis Creuzot on 15/10/2018.\n//  Copyright © 2018 alexiscreuzo"
  },
  {
    "path": "KAPinField/Example/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1590,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "KAPinField/Example/Assets.xcassets/Contents.json",
    "chars": 62,
    "preview": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "KAPinField/Example/Base.lproj/LaunchScreen.storyboard",
    "chars": 4664,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "KAPinField/Example/Base.lproj/Main.storyboard",
    "chars": 14731,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "KAPinField/Example/Info.plist",
    "chars": 1539,
    "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": "KAPinField/Example/ViewController.swift",
    "chars": 3795,
    "preview": "//\n//  ViewController.swift\n//  KAPinCode\n//\n//  Created by Alexis Creuzot on 15/10/2018.\n//  Copyright © 2018 alexiscre"
  },
  {
    "path": "KAPinField/Sources/Info.plist",
    "chars": 726,
    "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": "KAPinField/Sources/KAPinField.h",
    "chars": 507,
    "preview": "//\n//  KAPinField.h\n//  KAPinField\n//\n//  Created by Basem Emara on 2019-04-16.\n//  Copyright © 2019 alexiscreuzot. All "
  },
  {
    "path": "KAPinField/Sources/KAPinField.swift",
    "chars": 25326,
    "preview": "//\n//  KAPinField.swift\n//  KAPinCode\n//\n//  Created by Alexis Creuzot on 15/10/2018.\n//  Copyright © 2018 alexiscreuzot"
  },
  {
    "path": "KAPinField.podspec",
    "chars": 584,
    "preview": "Pod::Spec.new do |s|\n  s.name             = 'KAPinField'\n  s.version          =  '5.0.3'\n  s.summary          = 'Lightwe"
  },
  {
    "path": "KAPinField.xcodeproj/project.pbxproj",
    "chars": 20099,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 50;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "KAPinField.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 205,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:/Users/alex/Dev"
  },
  {
    "path": "KAPinField.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": "KAPinField.xcodeproj/xcshareddata/xcschemes/KAPinField iOS.xcscheme",
    "chars": 2783,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1200\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "KAPinField.xcodeproj/xcshareddata/xcschemes/KAPinField.xcscheme",
    "chars": 3233,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1200\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "KAPinField.xcworkspace/contents.xcworkspacedata",
    "chars": 160,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"container:KAPinField"
  },
  {
    "path": "KAPinField.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": "LICENSE",
    "chars": 1071,
    "preview": "MIT License\n\nCopyright (c) 2018 Alexis Creuzot\n\nPermission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "Package.swift",
    "chars": 697,
    "preview": "// swift-tools-version:5.4\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"KAPinField\",\n    platforms: [\n "
  },
  {
    "path": "README.md",
    "chars": 4714,
    "preview": "[![Platform](https://img.shields.io/cocoapods/p/KAPinField.svg?style=flat)](https://alamofire.github.io/KAPinField)\n[![L"
  }
]

About this extraction

This page contains the full source code of the kirualex/KAPinField GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 25 files (87.1 KB), approximately 23.8k 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.

Copied to clipboard!