├── Example
├── Screens
│ └── dark1.gif
├── Demo1-not library
│ ├── CreditCardForm
│ │ ├── Assets.xcassets
│ │ │ ├── Contents.json
│ │ │ ├── Amex.imageset
│ │ │ │ ├── amex.png
│ │ │ │ └── Contents.json
│ │ │ ├── Visa.imageset
│ │ │ │ ├── visa (1).png
│ │ │ │ └── Contents.json
│ │ │ ├── chip.imageset
│ │ │ │ ├── CC_chip.png
│ │ │ │ └── Contents.json
│ │ │ ├── Discover.imageset
│ │ │ │ ├── discover.png
│ │ │ │ └── Contents.json
│ │ │ ├── MasterCard.imageset
│ │ │ │ ├── mastercard.png
│ │ │ │ └── Contents.json
│ │ │ ├── JCB.imageset
│ │ │ │ ├── 1478638835_jcb_card_payment.png
│ │ │ │ └── Contents.json
│ │ │ ├── Diners Club.imageset
│ │ │ │ ├── 1478638761_dinner_club.png
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── AppDelegate.swift
│ │ └── ViewController.swift
│ ├── CreditCardForm.xcworkspace
│ │ ├── xcuserdata
│ │ │ └── atakishiyev.xcuserdatad
│ │ │ │ ├── xcdebugger
│ │ │ │ └── Breakpoints_v2.xcbkptlist
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ ├── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── contents.xcworkspacedata
│ ├── Podfile
│ └── Podfile.lock
└── Demo2-CreditCardFormLibarary
│ ├── Demo
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── JCB.imageset
│ │ │ ├── JCB.png
│ │ │ └── Contents.json
│ │ ├── Amex.imageset
│ │ │ ├── Amex.png
│ │ │ └── Contents.json
│ │ ├── Visa.imageset
│ │ │ ├── Visa.png
│ │ │ └── Contents.json
│ │ ├── chip.imageset
│ │ │ ├── chip.png
│ │ │ └── Contents.json
│ │ ├── Discover.imageset
│ │ │ ├── Discover.png
│ │ │ └── Contents.json
│ │ ├── Diners Club.imageset
│ │ │ ├── Diners Club.png
│ │ │ └── Contents.json
│ │ ├── Mastercard.imageset
│ │ │ ├── Mastercard.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── CreditCardForm.xcworkspace
│ │ ├── xcuserdata
│ │ │ └── atakishiyev.xcuserdatad
│ │ │ │ ├── xcdebugger
│ │ │ │ └── Breakpoints_v2.xcbkptlist
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ └── contents.xcworkspacedata
│ ├── TextField.swift
│ ├── Info.plist
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── AppDelegate.swift
│ └── ViewController.swift
│ ├── Demo.xcworkspace
│ ├── xcuserdata
│ │ └── atakishiyev.xcuserdatad
│ │ │ ├── xcdebugger
│ │ │ └── Breakpoints_v2.xcbkptlist
│ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── xcschemes
│ │ └── Demo.xcscheme
│ ├── Demo.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ │ └── atakishiyev.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ ├── xcuserdata
│ │ └── atakishiyev.xcuserdatad
│ │ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── project.pbxproj
│ ├── Podfile
│ └── Podfile.lock
├── CreditCardForm
├── Images.xcassets
│ ├── Contents.json
│ ├── JCB.imageset
│ │ ├── JCB.png
│ │ └── Contents.json
│ ├── Amex.imageset
│ │ ├── Amex.png
│ │ └── Contents.json
│ ├── Visa.imageset
│ │ ├── Visa.png
│ │ └── Contents.json
│ ├── chip.imageset
│ │ ├── chip.png
│ │ └── Contents.json
│ ├── amexCvc.imageset
│ │ ├── Group-1.png
│ │ ├── Group.png
│ │ └── Contents.json
│ ├── Discover.imageset
│ │ ├── Discover.png
│ │ └── Contents.json
│ ├── UnionPay.imageset
│ │ ├── UnionPay.png
│ │ └── Contents.json
│ ├── MasterCard.imageset
│ │ ├── Mastercard.png
│ │ └── Contents.json
│ └── Diners Club.imageset
│ │ ├── Diners Club.png
│ │ └── Contents.json
├── Classes
│ ├── AKMaskFieldEvent.swift
│ ├── AKMaskFieldStatus.swift
│ ├── CreditCardValidationType.swift
│ ├── AKMaskFieldPatternCharacter.swift
│ ├── AKMaskFieldBlockCharacter.swift
│ ├── Utilities.swift
│ ├── AKMaskFieldBlock.swift
│ ├── AKMaskFieldUtility.swift
│ ├── CreditCardValidator.swift
│ ├── AKMaskField.swift
│ └── CreditCardFormView.swift
└── CreditCardForm.h
├── CreditCardForm.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── atakishiyev.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── atakishiyev.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── xcshareddata
│ └── xcschemes
│ │ └── CreditCardForm.xcscheme
└── project.pbxproj
├── .gitignore
├── .travis.yml
├── CreditCardFormTests
├── Info.plist
└── CreditCardFormTests.swift
├── Info.plist
├── CreditCardForm.podspec
├── LICENSE
└── README.md
/Example/Screens/dark1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Screens/dark1.gif
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/JCB.imageset/JCB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/JCB.imageset/JCB.png
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/Amex.imageset/Amex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/Amex.imageset/Amex.png
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/Visa.imageset/Visa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/Visa.imageset/Visa.png
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/chip.imageset/chip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/chip.imageset/chip.png
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/amexCvc.imageset/Group-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/amexCvc.imageset/Group-1.png
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/amexCvc.imageset/Group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/amexCvc.imageset/Group.png
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/Discover.imageset/Discover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/Discover.imageset/Discover.png
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/UnionPay.imageset/UnionPay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/UnionPay.imageset/UnionPay.png
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/MasterCard.imageset/Mastercard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/MasterCard.imageset/Mastercard.png
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/Diners Club.imageset/Diners Club.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm/Images.xcassets/Diners Club.imageset/Diners Club.png
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Amex.imageset/amex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Amex.imageset/amex.png
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/JCB.imageset/JCB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/JCB.imageset/JCB.png
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Amex.imageset/Amex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Amex.imageset/Amex.png
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Visa.imageset/Visa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Visa.imageset/Visa.png
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/chip.imageset/chip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/chip.imageset/chip.png
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Visa.imageset/visa (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Visa.imageset/visa (1).png
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/chip.imageset/CC_chip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo1-not library/CreditCardForm/Assets.xcassets/chip.imageset/CC_chip.png
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Discover.imageset/discover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Discover.imageset/discover.png
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Discover.imageset/Discover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Discover.imageset/Discover.png
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/MasterCard.imageset/mastercard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo1-not library/CreditCardForm/Assets.xcassets/MasterCard.imageset/mastercard.png
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Diners Club.imageset/Diners Club.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Diners Club.imageset/Diners Club.png
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Mastercard.imageset/Mastercard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Mastercard.imageset/Mastercard.png
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/CreditCardForm.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/CreditCardForm.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/JCB.imageset/1478638835_jcb_card_payment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo1-not library/CreditCardForm/Assets.xcassets/JCB.imageset/1478638835_jcb_card_payment.png
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Diners Club.imageset/1478638761_dinner_club.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Diners Club.imageset/1478638761_dinner_club.png
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CreditCardForm.xcodeproj/project.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/CreditCardForm.xcodeproj/project.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo1-not library/CreditCardForm.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | ## Build generated
4 | build/
5 | DerivedData/
6 |
7 | Example/Demo1-not library/Pods/
8 | Example/Demo2-CreditCardFormLibarary/Pods/
9 |
10 | CreditCardFormTests/
11 | CreditCardForm.xcodeproj/project.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate
12 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/CreditCardForm.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo/CreditCardForm.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcodeproj/project.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orazz/CreditCardForm-iOS/HEAD/Example/Demo2-CreditCardFormLibarary/Demo.xcodeproj/project.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/CreditCardForm.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | osx_image: xcode11
2 | language: objective-c
3 | podfile: Example/Demo2-CreditCardFormLibarary/Podfile
4 | before_install:
5 | - gem install cocoapods
6 | - pod repo update
7 | - pod install --project-directory=Example/Demo2-CreditCardFormLibarary/
8 | script: xcodebuild -workspace Example/Demo2-CreditCardFormLibarary/Demo.xcworkspace -scheme Demo -sdk iphonesimulator
9 |
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/JCB.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "JCB.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/Amex.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Amex.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/Visa.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Visa.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/chip.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "chip.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/Discover.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Discover.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/UnionPay.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "UnionPay.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/MasterCard.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Mastercard.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/CreditCardForm.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/Diners Club.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Diners Club.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Amex.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "amex.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Amex.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Amex.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/JCB.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "JCB.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Visa.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Visa.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/chip.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "chip.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment the next line to define a global platform for your project
2 | platform :ios, '9.0'
3 |
4 | target 'Demo' do
5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
6 | use_frameworks!
7 |
8 | # Pods for Demo
9 | pod "Stripe"
10 | pod 'CreditCardForm', :git => 'https://github.com/orazz/CreditCardForm-iOS', branch: 'master'
11 | # pod 'CreditCardForm'
12 | end
13 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Visa.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "visa (1).png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/chip.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "CC_chip.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Discover.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "discover.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/MasterCard.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mastercard.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Discover.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Discover.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/CreditCardForm/Classes/AKMaskFieldEvent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AKMaskFieldEvent.swift
3 | // AKMaskField
4 | // GitHub: https://github.com/artemkrachulov/AKMaskField
5 | //
6 | // Created by Artem Krachulov
7 | // Copyright (c) 2016 Artem Krachulov. All rights reserved.
8 | // Website: http://www.artemkrachulov.com/
9 | //
10 |
11 | /// Event constant value received after manipulations with the Mask Field.
12 | enum AKMaskFieldEvent {
13 | case error, insert, delete ,replace
14 | }
15 |
--------------------------------------------------------------------------------
/CreditCardForm/Classes/AKMaskFieldStatus.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AKMaskFieldStatus.swift
3 | // AKMaskField
4 | // GitHub: https://github.com/artemkrachulov/AKMaskField
5 | //
6 | // Created by Artem Krachulov
7 | // Copyright (c) 2016 Artem Krachulov. All rights reserved.
8 | // Website: http://www.artemkrachulov.com/
9 | //
10 |
11 | /// The Mask Field, Block and Block Character status property constant.
12 | enum AKMaskFieldStatus {
13 | case clear, incomplete, complete
14 | }
15 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment the next line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | target 'CreditCardForm' do
5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
6 | use_frameworks!
7 |
8 | # Pods for CreditCardForm
9 | pod "Stripe"
10 | pod 'AKMaskField', :git => 'https://github.com/artemkrachulov/AKMaskField.git', :tag => 'v2.0.1'
11 | pod "CreditCardValidator"
12 | end
13 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Diners Club.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Diners Club.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/Mastercard.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "Mastercard.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/JCB.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1478638835_jcb_card_payment.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/CreditCardForm/Images.xcassets/amexCvc.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "filename" : "Group.png",
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "filename" : "Group-1.png",
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/Diners Club.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "1478638761_dinner_club.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcworkspace/xcuserdata/atakishiyev.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Demo.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcodeproj/xcuserdata/atakishiyev.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SuppressBuildableAutocreation
8 |
9 | 8EC8C45A1DED83D10044FB44
10 |
11 | primary
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/CreditCardForm/CreditCardForm.h:
--------------------------------------------------------------------------------
1 | //
2 | // CreditCardForm.h
3 | // CreditCardForm
4 | //
5 | // Created by Atakishiyev Orazdurdy on 11/28/16.
6 | // Copyright © 2016 Veriloft. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for CreditCardForm.
12 | FOUNDATION_EXPORT double CreditCardFormVersionNumber;
13 |
14 | //! Project version string for CreditCardForm.
15 | FOUNDATION_EXPORT const unsigned char CreditCardFormVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/TextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextField.swift
3 | // Demo
4 | //
5 | // Created by Oraz Atakishiyev on 5/30/20.
6 | // Copyright © 2020 Veriloft. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class TextField: UITextField {
12 |
13 | let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
14 |
15 | override open func textRect(forBounds bounds: CGRect) -> CGRect {
16 | return bounds.inset(by: padding)
17 | }
18 |
19 | override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
20 | return bounds.inset(by: padding)
21 | }
22 |
23 | override open func editingRect(forBounds bounds: CGRect) -> CGRect {
24 | return bounds.inset(by: padding)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/CreditCardForm.xcodeproj/xcuserdata/atakishiyev.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | CreditCardForm.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 8EC8C3C81DEC8C3E0044FB44
16 |
17 | primary
18 |
19 |
20 | 8EC8C3D11DEC8C3E0044FB44
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/CreditCardFormTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - CreditCardForm (0.2.0)
3 | - Stripe (17.0.3)
4 |
5 | DEPENDENCIES:
6 | - CreditCardForm (from `https://github.com/orazz/CreditCardForm-iOS`, branch `master`)
7 | - Stripe
8 |
9 | SPEC REPOS:
10 | trunk:
11 | - Stripe
12 |
13 | EXTERNAL SOURCES:
14 | CreditCardForm:
15 | :branch: master
16 | :git: https://github.com/orazz/CreditCardForm-iOS
17 |
18 | CHECKOUT OPTIONS:
19 | CreditCardForm:
20 | :commit: dbafedcf6ecebb7d6c6b75d1f3bc8787a95e5b10
21 | :git: https://github.com/orazz/CreditCardForm-iOS
22 |
23 | SPEC CHECKSUMS:
24 | CreditCardForm: bba4aad545236f97f2dc45ea3bed0cb57d5e0e99
25 | Stripe: 30ba9a2ac7297e93de561fed695222ef980ee521
26 |
27 | PODFILE CHECKSUM: b70fd5f5c314cafe698f9253d5a630d5a098ec25
28 |
29 | COCOAPODS: 1.8.4
30 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - AKMaskField (2.0.1)
3 | - CreditCardValidator (0.3.2)
4 | - Stripe (8.0.7)
5 |
6 | DEPENDENCIES:
7 | - AKMaskField (from `https://github.com/artemkrachulov/AKMaskField.git`, tag `v2.0.1`)
8 | - CreditCardValidator
9 | - Stripe
10 |
11 | EXTERNAL SOURCES:
12 | AKMaskField:
13 | :git: https://github.com/artemkrachulov/AKMaskField.git
14 | :tag: v2.0.1
15 |
16 | CHECKOUT OPTIONS:
17 | AKMaskField:
18 | :git: https://github.com/artemkrachulov/AKMaskField.git
19 | :tag: v2.0.1
20 |
21 | SPEC CHECKSUMS:
22 | AKMaskField: cf9e98c5ebd459998f5db1bdc6e810479a865063
23 | CreditCardValidator: f2e0fc0f273e3f303513d35745df23d336eb1d67
24 | Stripe: 2bb9646115745d0ee8c7799e6872c57ba5dc6cc5
25 |
26 | PODFILE CHECKSUM: 52647c88b71ca77c6f2e3325345490e01c88351e
27 |
28 | COCOAPODS: 1.1.0.rc.2
29 |
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/CreditCardForm/Classes/CreditCardValidationType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CreditCardValidationType.swift
3 | //
4 | // Created by Vitaliy Kuzmenko on 02/06/15.
5 | // Copyright (c) 2015. All rights reserved.
6 | //
7 |
8 | import Foundation
9 |
10 | public func ==(lhs: CreditCardValidationType, rhs: CreditCardValidationType) -> Bool {
11 | return lhs.name == rhs.name
12 | }
13 |
14 | public struct CreditCardValidationType: Equatable {
15 |
16 | public var name: String
17 |
18 | public var regex: String
19 |
20 | public init(dict: [String: Any]) {
21 | if let name = dict["name"] as? String {
22 | self.name = name
23 | } else {
24 | self.name = ""
25 | }
26 |
27 | if let regex = dict["regex"] as? String {
28 | self.regex = regex
29 | } else {
30 | self.regex = ""
31 | }
32 | }
33 |
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/CreditCardForm/Classes/AKMaskFieldPatternCharacter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AKMaskFieldPatternCharacter.swift
3 | // AKMaskField
4 | // GitHub: https://github.com/artemkrachulov/AKMaskField
5 | //
6 | // Created by Artem Krachulov
7 | // Copyright (c) 2016 Artem Krachulov. All rights reserved.
8 | // Website: http://www.artemkrachulov.com/
9 | //
10 |
11 | /// Single block character pattern constant.
12 | enum AKMaskFieldPatternCharacter: String {
13 |
14 | // MARK: - Constants
15 |
16 | case NumberDecimal = "d"
17 | case NonDecimal = "D"
18 | case NonWord = "W"
19 | case Alphabet = "a"
20 | case AnyChar = "."
21 |
22 | /// Returns regular expression pattern.
23 | func pattern() -> String {
24 | switch self {
25 | case .NumberDecimal : return "\\d"
26 | case .NonDecimal : return "\\D"
27 | case .NonWord : return "\\W"
28 | case .Alphabet : return "[a-zA-Z]"
29 | default : return "."
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/CreditCardForm.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "CreditCardForm"
4 | s.version = "0.2.0"
5 | s.summary = "CreditCardForm is iOS framework"
6 |
7 | s.description = "CreditCardForm is iOS framework that allows developers to create the UI which replicates an actual Credit Card"
8 | s.homepage = "https://github.com/CreditCardForm"
9 | s.screenshots = 'https://camo.githubusercontent.com/e30bcc0537ff4aa4adae4f39ad664aeb2fd7db76/68747470733a2f2f646f746a70672e636f2f3862752e706e67'
10 | s.license = { :type => "MIT" }
11 | s.author = { "orazz" => "orazz.tm@gmail.com" }
12 | s.platform = :ios, "8.0"
13 | s.source = { :git => "https://github.com/orazz/CreditCardForm-iOS.git", :tag => s.version.to_s }
14 |
15 | s.ios.deployment_target = '8.0'
16 |
17 | s.source_files = "CreditCardForm/Classes/*.swift", "CreditCardForm/*.{h,m}"
18 | s.resource_bundles = {
19 | 'CreditCardForm' => ['CreditCardForm/Images.xcassets']
20 | }
21 | s.frameworks = 'UIKit'
22 | s.swift_versions = "4.2"
23 | end
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 - 2017 Orazz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/CreditCardFormTests/CreditCardFormTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CreditCardFormTests.swift
3 | // CreditCardFormTests
4 | //
5 | // Created by Atakishiyev Orazdurdy on 11/28/16.
6 | // Copyright © 2016 Veriloft. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import CreditCardForm
11 |
12 | class CreditCardFormTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/CreditCardForm/Classes/AKMaskFieldBlockCharacter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AKMaskFieldBlockCharacter.swift
3 | // AKMaskField
4 | // GitHub: https://github.com/artemkrachulov/AKMaskField
5 | //
6 | // Created by Artem Krachulov
7 | // Copyright (c) 2016 Artem Krachulov. All rights reserved.
8 | // Website: http://www.artemkrachulov.com/
9 | //
10 |
11 | import Foundation
12 |
13 | /// A structure that contains the block character main properties.
14 | public struct AKMaskFieldBlockCharacter {
15 |
16 | // MARK: - General
17 |
18 | /// Character index in the block.
19 | var index: Int
20 |
21 | /// The block index in the mask.
22 | var blockIndex: Int
23 |
24 | /// Current character status.
25 | var status: AKMaskFieldStatus
26 |
27 | // MARK: - Pattern
28 |
29 | /// The mask pattern character.
30 | var pattern: AKMaskFieldPatternCharacter!
31 |
32 | /// Location of the pattern character in the mask.
33 | var patternRange: NSRange
34 |
35 | // MARK: - Mask template
36 |
37 | /// The mask template character.
38 | var template: Character!
39 |
40 | /// Location of the mask template character in the mask template.
41 | var templateRange: NSRange
42 | }
--------------------------------------------------------------------------------
/CreditCardForm/Classes/Utilities.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Utilities.swift
3 | // CreditCardForm
4 | //
5 | // Created by Atakishiyev Orazdurdy on 11/29/16.
6 | // Copyright © 2016 Veriloft. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | class func hexStr ( hexStr : NSString, alpha : CGFloat) -> UIColor {
13 | let hexStr = hexStr.replacingOccurrences(of: "#", with: "")
14 | let scanner = Scanner(string: hexStr as String)
15 | var color: UInt32 = 0
16 | if scanner.scanHexInt32(&color) {
17 | let r = CGFloat((color & 0xFF0000) >> 16) / 255.0
18 | let g = CGFloat((color & 0x00FF00) >> 8) / 255.0
19 | let b = CGFloat(color & 0x0000FF) / 255.0
20 | return UIColor(red:r,green:g,blue:b,alpha:alpha)
21 | } else {
22 | print("invalid hex string", terminator: "")
23 | return UIColor.white;
24 | }
25 | }
26 | }
27 |
28 | extension Bundle {
29 | /// Create a new Bundle instance for 'Image.xcassets'.
30 | ///
31 | /// - Returns: a new bundle which contains 'Image.xcassets'.
32 | static func currentBundle() -> Bundle {
33 | let bundle = Bundle(for: CreditCardFormView.self)
34 | if let path = bundle.path(forResource: "CreditCardForm", ofType: "bundle") {
35 | return Bundle(path: path)!
36 | } else {
37 | return bundle
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/CreditCardForm/Classes/AKMaskFieldBlock.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AKMaskFieldBlock.swift
3 | // AKMaskField
4 | // GitHub: https://github.com/artemkrachulov/AKMaskField
5 | //
6 | // Created by Artem Krachulov
7 | // Copyright (c) 2016 Artem Krachulov. All rights reserved.
8 | // Website: http://www.artemkrachulov.com/
9 | //
10 |
11 | import Foundation
12 |
13 | /// A structure that contains the mask block main properties.
14 | public struct AKMaskFieldBlock {
15 |
16 | // MARK: - General
17 |
18 | /// Block index in the mask
19 | var index: Int
20 |
21 | /// Returns the current block status.
22 | var status: AKMaskFieldStatus {
23 |
24 | let completedChars: [AKMaskFieldBlockCharacter] = chars.filter { return $0.status != .clear }
25 |
26 | switch completedChars.count {
27 | case 0 : return .clear
28 | case chars.count : return .complete
29 | default : return .incomplete
30 | }
31 | }
32 |
33 | /// An array containing all characters inside block.
34 | var chars: [AKMaskFieldBlockCharacter]
35 |
36 | // MARK: - Pattern
37 |
38 | /// The mask pattern that represent current block.
39 | var pattern: String {
40 |
41 | var pattern: String = ""
42 | for char in chars {
43 | pattern += char.pattern.rawValue
44 | }
45 | return pattern
46 | }
47 |
48 | /// Location of the mask pattern in the mask.
49 | var patternRange: NSRange {
50 | return NSMakeRange(chars.first!.patternRange.location, chars.count)
51 | }
52 |
53 | // MARK: - Mask template
54 |
55 | /// The mask template string that represent current block.
56 | var template: String {
57 | var template: String = ""
58 | for char in chars {
59 | template.append(char.template)
60 | }
61 | return template
62 | }
63 |
64 | /// Location of the mask template string in the mask template.
65 | var templateRange: NSRange {
66 | return NSMakeRange(chars.first!.templateRange.location, chars.count)
67 | }
68 |
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // CreditCardForum
4 | //
5 | // Created by Atakishiyev Orazdurdy on 11/5/16.
6 | // Copyright © 2016 Veriloft. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Demo
4 | //
5 | // Created by Atakishiyev Orazdurdy on 11/29/16.
6 | // Copyright © 2016 Veriloft. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcworkspace/xcshareddata/xcschemes/Demo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/CreditCardForm/Classes/AKMaskFieldUtility.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AKMaskFieldUtility.swift
3 | // AKMaskField
4 | // GitHub: https://github.com/artemkrachulov/AKMaskField
5 | //
6 | // Created by Artem Krachulov
7 | // Copyright (c) 2016 Artem Krachulov. All rights reserved.
8 | // Website: http://www.artemkrachulov.com/
9 | //
10 |
11 | import UIKit
12 |
13 | class AKMaskFieldUtility {
14 |
15 | /// [Source](http://stackoverflow.com/questions/25138339/nsrange-to-rangestring-index)
16 | class func rangeFromString(_ string: String, nsRange: NSRange) -> Range! {
17 |
18 |
19 | guard
20 | let from16 = string.utf16.index(string.utf16.startIndex, offsetBy: nsRange.location, limitedBy: string.utf16.endIndex),
21 | let to16 = string.utf16.index(from16, offsetBy: nsRange.length, limitedBy: string.utf16.endIndex),
22 | let from = String.Index(from16, within: string),
23 | let to = String.Index(to16, within: string)
24 | else { return nil }
25 | return from ..< to
26 | /*
27 |
28 | let from16 = string.utf16.startIndex.advancedBy(nsRange.location, limit: string.utf16.endIndex)
29 | let to16 = from16.advancedBy(nsRange.length, limit: string.utf16.endIndex)
30 |
31 | if let from = String.Index(from16, within: string),
32 | let to = String.Index(to16, within: string) {
33 | return from ..< to
34 | }
35 | return nil*/
36 | }
37 |
38 | class func substring(_ sourceString: String?, withNSRange range: NSRange) -> String {
39 | guard let sourceString = sourceString else {
40 | return ""
41 | }
42 | #if swift(>=4)
43 | return String(sourceString[rangeFromString(sourceString, nsRange: range)])
44 | #else
45 | return sourceString.substring(with: rangeFromString(sourceString, nsRange: range))
46 | #endif
47 | }
48 |
49 | class func replace(_ sourceString: inout String!, withString string: String, inRange range: NSRange) {
50 | sourceString = sourceString.replacingCharacters(in: rangeFromString(sourceString, nsRange: range), with: string)
51 | }
52 |
53 | class func replacingOccurrencesOfString(_ string: inout String!, target: String, withString replacement: String) {
54 | string = string.replacingOccurrences(of: target, with: replacement, options: .regularExpression, range: nil)
55 | }
56 |
57 | class func maskField(_ maskField: UITextField, moveCaretToPosition position: Int) {
58 | guard let caretPosition = maskField.position(from: maskField.beginningOfDocument, offset: position) else {
59 | return
60 | }
61 |
62 | maskField.selectedTextRange = maskField.textRange(from: caretPosition, to: caretPosition)
63 | }
64 |
65 | class func matchesInString(_ string: String, pattern: String) -> [NSTextCheckingResult] {
66 | return try!
67 | NSRegularExpression(pattern: pattern, options: .caseInsensitive)
68 | .matches(in: string, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, string.count))
69 | }
70 |
71 | class func findIntersection(_ ranges: [NSRange], withRange range: NSRange) -> [NSRange?] {
72 |
73 | var intersectRanges = [NSRange?]()
74 |
75 | for r in ranges {
76 |
77 | var intersectRange: NSRange!
78 |
79 | let delta = r.location - range.location
80 | var location, length, tail: Int
81 |
82 | if delta <= 0 {
83 | location = range.location
84 | length = range.length
85 | tail = r.length - abs(delta)
86 | } else {
87 | location = r.location
88 | length = r.length
89 | tail = range.length - abs(delta)
90 | }
91 |
92 | if tail > 0 && length > 0 {
93 | intersectRange = NSMakeRange(location, min(tail, length))
94 | }
95 |
96 | intersectRanges.append(intersectRange)
97 | }
98 | return intersectRanges
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/CreditCardForm.xcodeproj/xcshareddata/xcschemes/CreditCardForm.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
63 |
69 |
70 |
71 |
72 |
78 |
79 |
85 |
86 |
87 |
88 |
90 |
91 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/CreditCardForm/Classes/CreditCardValidator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CreditCardValidator.swift
3 | //
4 | // Created by Vitaliy Kuzmenko on 02/06/15.
5 | // Copyright (c) 2015. All rights reserved.
6 | //
7 |
8 | import Foundation
9 |
10 | public class CreditCardValidator {
11 |
12 | public lazy var types: [CreditCardValidationType] = {
13 | var types = [CreditCardValidationType]()
14 | for object in CreditCardValidator.types {
15 | types.append(CreditCardValidationType(dict: object))
16 | }
17 | return types
18 | }()
19 |
20 | public init() { }
21 |
22 | /**
23 | Get card type from string
24 |
25 | - parameter string: card number string
26 |
27 | - returns: CreditCardValidationType structure
28 | */
29 | public func type(from string: String) -> CreditCardValidationType? {
30 | for type in types {
31 | let predicate = NSPredicate(format: "SELF MATCHES %@", type.regex)
32 | let numbersString = self.onlyNumbers(string: string)
33 | if predicate.evaluate(with: numbersString) {
34 | return type
35 | }
36 | }
37 | return nil
38 | }
39 |
40 | /**
41 | Validate card number
42 |
43 | - parameter string: card number string
44 |
45 | - returns: true or false
46 | */
47 | public func validate(string: String) -> Bool {
48 | let numbers = self.onlyNumbers(string: string)
49 | if numbers.count < 9 {
50 | return false
51 | }
52 |
53 | var reversedString = ""
54 | let range: Range = numbers.startIndex.. () in
57 | reversedString += substring!
58 | }
59 |
60 | var oddSum = 0, evenSum = 0
61 | let reversedArray = reversedString
62 |
63 | for (i, s) in reversedArray.enumerated() {
64 |
65 | let digit = Int(String(s))!
66 |
67 | if i % 2 == 0 {
68 | evenSum += digit
69 | } else {
70 | oddSum += digit / 5 + (2 * digit) % 10
71 | }
72 | }
73 | return (oddSum + evenSum) % 10 == 0
74 | }
75 |
76 | /**
77 | Validate card number string for type
78 |
79 | - parameter string: card number string
80 | - parameter type: CreditCardValidationType structure
81 |
82 | - returns: true or false
83 | */
84 | public func validate(string: String, forType type: CreditCardValidationType) -> Bool {
85 | return self.type(from: string) == type
86 | }
87 |
88 | public func onlyNumbers(string: String) -> String {
89 | let set = CharacterSet.decimalDigits.inverted
90 | let numbers = string.components(separatedBy: set)
91 | return numbers.joined(separator: "")
92 | }
93 |
94 | // MARK: - Loading data
95 |
96 | private static let types = [
97 | [
98 | "name": "Amex",
99 | "regex": "^3[47][0-9]{5,}$"
100 | ], [
101 | "name": "Visa",
102 | "regex": "^4[0-9]{6,}$"
103 | ], [
104 | "name": "MasterCard",
105 | "regex": "^5[1-5][0-9]{5,}$"
106 | ], [
107 | "name": "Maestro",
108 | "regex": "^(?:5[0678]\\d\\d|6304|6390|67\\d\\d)\\d{8,15}$"
109 | ], [
110 | "name": "Diners Club",
111 | "regex": "^3(?:0[0-5]|[68][0-9])[0-9]{4,}$"
112 | ], [
113 | "name": "JCB",
114 | "regex": "^(?:2131|1800|35[0-9]{3})[0-9]{3,}$"
115 | ], [
116 | "name": "Discover",
117 | "regex": "^6(?:011|5[0-9]{2})[0-9]{3,}$"
118 | ], [
119 | "name": "UnionPay",
120 | "regex": "^62[0-5]\\d{13,16}$"
121 | ]
122 | ]
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // Demo
4 | //
5 | // Created by Atakishiyev Orazdurdy on 11/29/16.
6 | // Copyright © 2016 Veriloft. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Stripe
11 | import CreditCardForm
12 |
13 | class ViewController: UIViewController, STPPaymentCardTextFieldDelegate {
14 |
15 | @IBOutlet weak var creditCardView: CreditCardFormView!
16 | let paymentTextField = STPPaymentCardTextField()
17 | private var cardHolderNameTextField: TextField!
18 | private var cardParams: STPPaymentMethodCardParams!
19 |
20 | override func viewDidLoad() {
21 | super.viewDidLoad()
22 | creditCardView.cardHolderString = "Oraz Atakishiyev"
23 | creditCardView.cardGradientColors[Brands.Amex.rawValue] = [UIColor.red, UIColor.black]
24 | creditCardView.cardNumberFont = UIFont(name: "HelveticaNeue", size: 20)!
25 | creditCardView.cardPlaceholdersFont = UIFont(name: "HelveticaNeue", size: 10)!
26 | creditCardView.cardTextFont = UIFont(name: "HelveticaNeue", size: 12)!
27 |
28 | paymentTextField.postalCodeEntryEnabled = false
29 |
30 | createTextField()
31 |
32 | cardParams = STPPaymentMethodCardParams()
33 | cardParams.number = "375987654321111"
34 | cardParams.expMonth = 03
35 | cardParams.expYear = 23
36 | cardParams.cvc = "7997"
37 | self.paymentTextField.cardParams = cardParams
38 | }
39 |
40 | override func viewDidAppear(_ animated: Bool) {
41 | super.viewDidAppear(animated)
42 |
43 | // load saved card params
44 | creditCardView.paymentCardTextFieldDidChange(cardNumber: cardParams.number, expirationYear: cardParams!.expYear as? UInt, expirationMonth: cardParams!.expMonth as? UInt, cvc: cardParams.cvc)
45 | }
46 |
47 | func createTextField() {
48 | cardHolderNameTextField = TextField(frame: CGRect(x: 15, y: 199, width: self.view.frame.size.width - 30, height: 44))
49 | cardHolderNameTextField.placeholder = "CARD HOLDER"
50 | cardHolderNameTextField.delegate = self
51 | cardHolderNameTextField.translatesAutoresizingMaskIntoConstraints = false
52 | cardHolderNameTextField.setBottomBorder()
53 | cardHolderNameTextField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: .editingChanged)
54 | view.addSubview(cardHolderNameTextField)
55 |
56 | paymentTextField.frame = CGRect(x: 15, y: 199, width: self.view.frame.size.width - 30, height: 44)
57 | paymentTextField.delegate = self
58 | paymentTextField.translatesAutoresizingMaskIntoConstraints = false
59 | paymentTextField.borderWidth = 0
60 |
61 | let border = CALayer()
62 | let width = CGFloat(1.0)
63 | border.borderColor = UIColor.darkGray.cgColor
64 | border.frame = CGRect(x: 0, y: paymentTextField.frame.size.height - width, width: paymentTextField.frame.size.width, height: paymentTextField.frame.size.height)
65 | border.borderWidth = width
66 | paymentTextField.layer.addSublayer(border)
67 | paymentTextField.layer.masksToBounds = true
68 |
69 | view.addSubview(paymentTextField)
70 |
71 | NSLayoutConstraint.activate([
72 | cardHolderNameTextField.topAnchor.constraint(equalTo: creditCardView.bottomAnchor, constant: 20),
73 | cardHolderNameTextField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
74 | cardHolderNameTextField.widthAnchor.constraint(equalToConstant: self.view.frame.size.width-25),
75 | cardHolderNameTextField.heightAnchor.constraint(equalToConstant: 44)
76 | ])
77 |
78 | NSLayoutConstraint.activate([
79 | paymentTextField.topAnchor.constraint(equalTo: cardHolderNameTextField.bottomAnchor, constant: 20),
80 | paymentTextField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
81 | paymentTextField.widthAnchor.constraint(equalToConstant: self.view.frame.size.width-20),
82 | paymentTextField.heightAnchor.constraint(equalToConstant: 44)
83 | ])
84 | }
85 |
86 | func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) {
87 | creditCardView.paymentCardTextFieldDidChange(cardNumber: textField.cardNumber, expirationYear: textField.expirationYear, expirationMonth: textField.expirationMonth, cvc: textField.cvc)
88 | }
89 |
90 | func paymentCardTextFieldDidEndEditingExpiration(_ textField: STPPaymentCardTextField) {
91 | creditCardView.paymentCardTextFieldDidEndEditingExpiration(expirationYear: textField.expirationYear)
92 | }
93 |
94 | func paymentCardTextFieldDidBeginEditingCVC(_ textField: STPPaymentCardTextField) {
95 | creditCardView.paymentCardTextFieldDidBeginEditingCVC()
96 | }
97 |
98 | func paymentCardTextFieldDidEndEditingCVC(_ textField: STPPaymentCardTextField) {
99 | creditCardView.paymentCardTextFieldDidEndEditingCVC()
100 | }
101 | }
102 |
103 | extension ViewController: UITextFieldDelegate {
104 | @objc func textFieldDidChange(_ textField: UITextField) {
105 | creditCardView.cardHolderString = textField.text!
106 | }
107 |
108 | func textFieldShouldReturn(_ textField: UITextField) -> Bool {
109 | if textField == cardHolderNameTextField {
110 | textField.resignFirstResponder()
111 | paymentTextField.becomeFirstResponder()
112 | } else if textField == paymentTextField {
113 | textField.resignFirstResponder()
114 | }
115 | return true
116 | }
117 | }
118 |
119 | extension UITextField {
120 |
121 | func setBottomBorder() {
122 | self.borderStyle = UITextField.BorderStyle.none
123 | let border = CALayer()
124 | let width = CGFloat(1.0)
125 | border.borderColor = UIColor.darkGray.cgColor
126 | border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height)
127 | border.borderWidth = width
128 | self.layer.addSublayer(border)
129 | self.layer.masksToBounds = true
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CreditCardForm
2 |
3 | [](https://travis-ci.org/orazz/CreditCardForm-iOS)
4 |
6 | [](https://github.com/Carthage/Carthage)
7 |
8 |
9 |
10 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=GSV5DLQRJ5AH2&lc=US&item_name=Oraz%20Atakishiyev&item_number=PageMenu¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted)
11 |
12 | CreditCardForm is iOS framework that allows developers to create the UI which replicates an actual Credit Card.
13 |
14 | Fixed typo use CreditCardForm instead ~~CreditCardForum~~
15 |
16 | ### Screenshots
17 |
18 |
19 | ## Example
20 |
21 | To run the example project, clone the repo, and run `pod install` from the Demo-\* directory first.
22 |
23 | ## Supported Cards
24 |
25 | - [x] MasterCard
26 | - [x] Visa
27 | - [x] JCB
28 | - [x] Diners
29 | - [x] Discover
30 | - [x] Amex
31 | - [x] UnionPay
32 |
33 | ## Requirements
34 |
35 | * Xcode 8
36 | * iOS 8.1+
37 |
38 | ## Installation
39 |
40 | #### Using [CocoaPods](http://cocoapods.org)
41 |
42 | CreditCardForm is available through CocoaPods. To install it, simply add the following line to your `Podfile`:
43 |
44 | ```ruby
45 | pod "CreditCardForm"
46 | ```
47 |
48 | #### Using [Carthage](https://github.com/Carthage/Carthage)
49 |
50 | CreditCardForm is available through Carthage. To install it, simply add the following line to your `Cartfile`:
51 |
52 | ```ruby
53 | github "orazz/CreditCardForm-iOS"
54 | ```
55 |
56 | #### Manually
57 |
58 | If you prefer not to use either of the aforementioned dependency managers, you can integrate CreditCardForm into your project manually.
59 |
60 | 1. Download and drop ```CreditCardForm``` in your project.
61 | 2. Done!
62 |
63 | ## Usage example
64 |
65 | First step: this framework integrated with Stripe, you must install [Stripe](https://stripe.com/docs/mobile/ios)
66 |
67 | #### Storyboard
68 | Create a view set a class CreditCardFormView (preferred frame size: 300x200).
69 | Following this you will have to go through a few simple steps outlined below in order to get everything up and running.
70 | ``` swift
71 | import Stripe
72 | import CreditCardForm
73 | ```
74 | #### Swift
75 | ``` swift
76 | @IBOutlet weak var creditCardForm: CreditCardFormView!
77 |
78 | // Stripe textField
79 | let paymentTextField = STPPaymentCardTextField()
80 | ```
81 |
82 | #### Add the following code in the viewDidLoad function in your view controller
83 |
84 | ```swift
85 | // Set up stripe textfield
86 | paymentTextField.frame = CGRect(x: 15, y: 199, width: self.view.frame.size.width - 30, height: 44)
87 | paymentTextField.translatesAutoresizingMaskIntoConstraints = false
88 | paymentTextField.borderWidth = 0
89 |
90 | let border = CALayer()
91 | let width = CGFloat(1.0)
92 | border.borderColor = UIColor.darkGray.cgColor
93 | border.frame = CGRect(x: 0, y: paymentTextField.frame.size.height - width, width: paymentTextField.frame.size.width, height: paymentTextField.frame.size.height)
94 | border.borderWidth = width
95 | paymentTextField.layer.addSublayer(border)
96 | paymentTextField.layer.masksToBounds = true
97 |
98 | view.addSubview(paymentTextField)
99 |
100 | NSLayoutConstraint.activate([
101 | paymentTextField.topAnchor.constraint(equalTo: creditCardForm.bottomAnchor, constant: 20),
102 | paymentTextField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
103 | paymentTextField.widthAnchor.constraint(equalToConstant: self.view.frame.size.width-20),
104 | paymentTextField.heightAnchor.constraint(equalToConstant: 44)
105 | ])
106 | ```
107 |
108 | #### Delegate Methods
109 |
110 | In order to use the delegate methods first set the delegate of Stripe to the parent view controller when setting it up
111 |
112 | ``` swift
113 | paymentTextField.delegate = self
114 | ```
115 |
116 | After that you will be able to set up the following delegate methods inside of your parent view controller
117 |
118 | ``` swift
119 | func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) {
120 | creditCardForm.paymentCardTextFieldDidChange(cardNumber: textField.cardNumber, expirationYear: textField.expirationYear, expirationMonth: textField.expirationMonth, cvc: textField.cvc)
121 | }
122 |
123 | func paymentCardTextFieldDidEndEditingExpiration(_ textField: STPPaymentCardTextField) {
124 | creditCardForm.paymentCardTextFieldDidEndEditingExpiration(expirationYear: textField.expirationYear)
125 | }
126 |
127 | func paymentCardTextFieldDidBeginEditingCVC(_ textField: STPPaymentCardTextField) {
128 | creditCardForm.paymentCardTextFieldDidBeginEditingCVC()
129 | }
130 |
131 | func paymentCardTextFieldDidEndEditingCVC(_ textField: STPPaymentCardTextField) {
132 | creditCardForm.paymentCardTextFieldDidEndEditingCVC()
133 | }
134 | ```
135 |
136 | **You should now be ready to use CreditCardForm!!**
137 |
138 | ## Customization
139 |
140 | **1) Colors**
141 | ``` swift
142 | creditCardForm.backgroundColor (UIColor)
143 | creditCardForm.cardHolderExpireDateColor (UIColor)
144 | creditCardForm.cardHolderExpireDateTextColor (UIColor)
145 | creditCardForm.backLineColor (UIColor)
146 |
147 | // Brands Color brand name, front color, back color
148 | [String: [UIColor]]
149 |
150 | creditCardForm.cardGradientColors[Brands.Visa.rawValue] = [UIColor.blue, UIColor.red]
151 |
152 | // Set font
153 | creditCardForm.cardNumberFont = UIFont(name: "FontName", size: 20)!
154 | creditCardForm.cardPlaceholdersFont = UIFont(name: "FontName", size: 10)!
155 | creditCardForm.cardTextFont = UIFont(name: "FontName", size: 12)!
156 | ```
157 | **2) Images**
158 | ``` swift
159 | creditCardForm.chipImage (UIImage)
160 | ```
161 | **3) Placeholders**
162 | ``` swift
163 | creditCardForm.cardHolderString (String)
164 | creditCardForm.expireDatePlaceholderText (String)
165 | ```
166 | **Card number: [Configuring the Mask Field](https://github.com/artemkrachulov/AKMaskField#configuring-the-mask-field)**
167 | ``` swift
168 | creditCardForm.cardNumberMaskExpression (String)
169 | creditCardForm.cardNumberMaskTemplate (String)
170 |
171 | creditCardForm.cardNumberFontSize (CGFloat)
172 | ```
173 | ## Contribute
174 |
175 | We would love for you to contribute to **CreditCardForm**, check the ``LICENSE`` file for more info.
176 |
177 | ## Meta
178 |
179 | [Oraz Atakishiyev](https://github.com/orazz), [orazz.com](https://orazz.com)
180 |
181 | #### 3rd party libraries
182 |
183 | [CreditCardValidator](https://github.com/vitkuzmenko/CreditCardValidator)
184 | [AKMaskField](https://github.com/artemkrachulov/AKMaskField)
185 |
186 | ## License
187 |
188 | CreditCardForm is available under the MIT license. See the LICENSE file for more info.
189 |
--------------------------------------------------------------------------------
/Example/Demo2-CreditCardFormLibarary/Demo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 8EA30DCE2482BE3900B53105 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EA30DCD2482BE3900B53105 /* TextField.swift */; };
11 | 8EC8C45F1DED83D10044FB44 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C45E1DED83D10044FB44 /* AppDelegate.swift */; };
12 | 8EC8C4611DED83D10044FB44 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4601DED83D10044FB44 /* ViewController.swift */; };
13 | 8EC8C4641DED83D10044FB44 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8EC8C4621DED83D10044FB44 /* Main.storyboard */; };
14 | 8EC8C4661DED83D10044FB44 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8EC8C4651DED83D10044FB44 /* Assets.xcassets */; };
15 | 8EC8C4691DED83D10044FB44 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8EC8C4671DED83D10044FB44 /* LaunchScreen.storyboard */; };
16 | D7EC8EC8DADC52E74838081D /* Pods_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AD1CB681857222D8D4AF1BC /* Pods_Demo.framework */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXCopyFilesBuildPhase section */
20 | 8EC8C4D91DED92620044FB44 /* Embed Frameworks */ = {
21 | isa = PBXCopyFilesBuildPhase;
22 | buildActionMask = 2147483647;
23 | dstPath = "";
24 | dstSubfolderSpec = 10;
25 | files = (
26 | );
27 | name = "Embed Frameworks";
28 | runOnlyForDeploymentPostprocessing = 0;
29 | };
30 | /* End PBXCopyFilesBuildPhase section */
31 |
32 | /* Begin PBXFileReference section */
33 | 1BA2AAEE0DEE33072083F3FD /* Pods-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig"; sourceTree = ""; };
34 | 3AD1CB681857222D8D4AF1BC /* Pods_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
35 | 8EA30DCD2482BE3900B53105 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = ""; };
36 | 8EC8C45B1DED83D10044FB44 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
37 | 8EC8C45E1DED83D10044FB44 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
38 | 8EC8C4601DED83D10044FB44 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
39 | 8EC8C4631DED83D10044FB44 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
40 | 8EC8C4651DED83D10044FB44 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
41 | 8EC8C4681DED83D10044FB44 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
42 | 8EC8C46A1DED83D10044FB44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
43 | CBFCE409C80D5996E69369E9 /* Pods-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.release.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig"; sourceTree = ""; };
44 | /* End PBXFileReference section */
45 |
46 | /* Begin PBXFrameworksBuildPhase section */
47 | 8EC8C4581DED83D10044FB44 /* Frameworks */ = {
48 | isa = PBXFrameworksBuildPhase;
49 | buildActionMask = 2147483647;
50 | files = (
51 | D7EC8EC8DADC52E74838081D /* Pods_Demo.framework in Frameworks */,
52 | );
53 | runOnlyForDeploymentPostprocessing = 0;
54 | };
55 | /* End PBXFrameworksBuildPhase section */
56 |
57 | /* Begin PBXGroup section */
58 | 8EC8C4521DED83D10044FB44 = {
59 | isa = PBXGroup;
60 | children = (
61 | 8EC8C45D1DED83D10044FB44 /* Demo */,
62 | 8EC8C45C1DED83D10044FB44 /* Products */,
63 | CDAF11DB2D7B559BEABEB94A /* Pods */,
64 | AC1394A317E29C6ADDFCE125 /* Frameworks */,
65 | );
66 | sourceTree = "";
67 | };
68 | 8EC8C45C1DED83D10044FB44 /* Products */ = {
69 | isa = PBXGroup;
70 | children = (
71 | 8EC8C45B1DED83D10044FB44 /* Demo.app */,
72 | );
73 | name = Products;
74 | sourceTree = "";
75 | };
76 | 8EC8C45D1DED83D10044FB44 /* Demo */ = {
77 | isa = PBXGroup;
78 | children = (
79 | 8EC8C45E1DED83D10044FB44 /* AppDelegate.swift */,
80 | 8EC8C4601DED83D10044FB44 /* ViewController.swift */,
81 | 8EC8C4621DED83D10044FB44 /* Main.storyboard */,
82 | 8EC8C4651DED83D10044FB44 /* Assets.xcassets */,
83 | 8EC8C4671DED83D10044FB44 /* LaunchScreen.storyboard */,
84 | 8EC8C46A1DED83D10044FB44 /* Info.plist */,
85 | 8EA30DCD2482BE3900B53105 /* TextField.swift */,
86 | );
87 | path = Demo;
88 | sourceTree = "";
89 | };
90 | AC1394A317E29C6ADDFCE125 /* Frameworks */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 3AD1CB681857222D8D4AF1BC /* Pods_Demo.framework */,
94 | );
95 | name = Frameworks;
96 | sourceTree = "";
97 | };
98 | CDAF11DB2D7B559BEABEB94A /* Pods */ = {
99 | isa = PBXGroup;
100 | children = (
101 | 1BA2AAEE0DEE33072083F3FD /* Pods-Demo.debug.xcconfig */,
102 | CBFCE409C80D5996E69369E9 /* Pods-Demo.release.xcconfig */,
103 | );
104 | name = Pods;
105 | sourceTree = "";
106 | };
107 | /* End PBXGroup section */
108 |
109 | /* Begin PBXNativeTarget section */
110 | 8EC8C45A1DED83D10044FB44 /* Demo */ = {
111 | isa = PBXNativeTarget;
112 | buildConfigurationList = 8EC8C46D1DED83D10044FB44 /* Build configuration list for PBXNativeTarget "Demo" */;
113 | buildPhases = (
114 | 7D3C87E15FC61D189894AE69 /* [CP] Check Pods Manifest.lock */,
115 | 8EC8C4571DED83D10044FB44 /* Sources */,
116 | 8EC8C4581DED83D10044FB44 /* Frameworks */,
117 | 8EC8C4591DED83D10044FB44 /* Resources */,
118 | 7D953CEABE5FF802CACA32E6 /* [CP] Embed Pods Frameworks */,
119 | 8EC8C4D91DED92620044FB44 /* Embed Frameworks */,
120 | );
121 | buildRules = (
122 | );
123 | dependencies = (
124 | );
125 | name = Demo;
126 | productName = Demo;
127 | productReference = 8EC8C45B1DED83D10044FB44 /* Demo.app */;
128 | productType = "com.apple.product-type.application";
129 | };
130 | /* End PBXNativeTarget section */
131 |
132 | /* Begin PBXProject section */
133 | 8EC8C4531DED83D10044FB44 /* Project object */ = {
134 | isa = PBXProject;
135 | attributes = {
136 | LastSwiftUpdateCheck = 0820;
137 | LastUpgradeCheck = 1000;
138 | ORGANIZATIONNAME = Veriloft;
139 | TargetAttributes = {
140 | 8EC8C45A1DED83D10044FB44 = {
141 | CreatedOnToolsVersion = 8.2;
142 | DevelopmentTeam = 683U48NZTT;
143 | LastSwiftMigration = 0910;
144 | ProvisioningStyle = Automatic;
145 | };
146 | };
147 | };
148 | buildConfigurationList = 8EC8C4561DED83D10044FB44 /* Build configuration list for PBXProject "Demo" */;
149 | compatibilityVersion = "Xcode 3.2";
150 | developmentRegion = English;
151 | hasScannedForEncodings = 0;
152 | knownRegions = (
153 | English,
154 | en,
155 | Base,
156 | );
157 | mainGroup = 8EC8C4521DED83D10044FB44;
158 | productRefGroup = 8EC8C45C1DED83D10044FB44 /* Products */;
159 | projectDirPath = "";
160 | projectRoot = "";
161 | targets = (
162 | 8EC8C45A1DED83D10044FB44 /* Demo */,
163 | );
164 | };
165 | /* End PBXProject section */
166 |
167 | /* Begin PBXResourcesBuildPhase section */
168 | 8EC8C4591DED83D10044FB44 /* Resources */ = {
169 | isa = PBXResourcesBuildPhase;
170 | buildActionMask = 2147483647;
171 | files = (
172 | 8EC8C4691DED83D10044FB44 /* LaunchScreen.storyboard in Resources */,
173 | 8EC8C4661DED83D10044FB44 /* Assets.xcassets in Resources */,
174 | 8EC8C4641DED83D10044FB44 /* Main.storyboard in Resources */,
175 | );
176 | runOnlyForDeploymentPostprocessing = 0;
177 | };
178 | /* End PBXResourcesBuildPhase section */
179 |
180 | /* Begin PBXShellScriptBuildPhase section */
181 | 7D3C87E15FC61D189894AE69 /* [CP] Check Pods Manifest.lock */ = {
182 | isa = PBXShellScriptBuildPhase;
183 | buildActionMask = 2147483647;
184 | files = (
185 | );
186 | inputPaths = (
187 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
188 | "${PODS_ROOT}/Manifest.lock",
189 | );
190 | name = "[CP] Check Pods Manifest.lock";
191 | outputPaths = (
192 | "$(DERIVED_FILE_DIR)/Pods-Demo-checkManifestLockResult.txt",
193 | );
194 | runOnlyForDeploymentPostprocessing = 0;
195 | shellPath = /bin/sh;
196 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
197 | showEnvVarsInLog = 0;
198 | };
199 | 7D953CEABE5FF802CACA32E6 /* [CP] Embed Pods Frameworks */ = {
200 | isa = PBXShellScriptBuildPhase;
201 | buildActionMask = 2147483647;
202 | files = (
203 | );
204 | inputPaths = (
205 | "${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh",
206 | "${BUILT_PRODUCTS_DIR}/CreditCardForm/CreditCardForm.framework",
207 | "${BUILT_PRODUCTS_DIR}/Stripe/Stripe.framework",
208 | );
209 | name = "[CP] Embed Pods Frameworks";
210 | outputPaths = (
211 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CreditCardForm.framework",
212 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Stripe.framework",
213 | );
214 | runOnlyForDeploymentPostprocessing = 0;
215 | shellPath = /bin/sh;
216 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh\"\n";
217 | showEnvVarsInLog = 0;
218 | };
219 | /* End PBXShellScriptBuildPhase section */
220 |
221 | /* Begin PBXSourcesBuildPhase section */
222 | 8EC8C4571DED83D10044FB44 /* Sources */ = {
223 | isa = PBXSourcesBuildPhase;
224 | buildActionMask = 2147483647;
225 | files = (
226 | 8EA30DCE2482BE3900B53105 /* TextField.swift in Sources */,
227 | 8EC8C4611DED83D10044FB44 /* ViewController.swift in Sources */,
228 | 8EC8C45F1DED83D10044FB44 /* AppDelegate.swift in Sources */,
229 | );
230 | runOnlyForDeploymentPostprocessing = 0;
231 | };
232 | /* End PBXSourcesBuildPhase section */
233 |
234 | /* Begin PBXVariantGroup section */
235 | 8EC8C4621DED83D10044FB44 /* Main.storyboard */ = {
236 | isa = PBXVariantGroup;
237 | children = (
238 | 8EC8C4631DED83D10044FB44 /* Base */,
239 | );
240 | name = Main.storyboard;
241 | sourceTree = "";
242 | };
243 | 8EC8C4671DED83D10044FB44 /* LaunchScreen.storyboard */ = {
244 | isa = PBXVariantGroup;
245 | children = (
246 | 8EC8C4681DED83D10044FB44 /* Base */,
247 | );
248 | name = LaunchScreen.storyboard;
249 | sourceTree = "";
250 | };
251 | /* End PBXVariantGroup section */
252 |
253 | /* Begin XCBuildConfiguration section */
254 | 8EC8C46B1DED83D10044FB44 /* Debug */ = {
255 | isa = XCBuildConfiguration;
256 | buildSettings = {
257 | ALWAYS_SEARCH_USER_PATHS = NO;
258 | CLANG_ANALYZER_NONNULL = YES;
259 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
260 | CLANG_CXX_LIBRARY = "libc++";
261 | CLANG_ENABLE_MODULES = YES;
262 | CLANG_ENABLE_OBJC_ARC = YES;
263 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
264 | CLANG_WARN_BOOL_CONVERSION = YES;
265 | CLANG_WARN_COMMA = YES;
266 | CLANG_WARN_CONSTANT_CONVERSION = YES;
267 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
268 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
269 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
270 | CLANG_WARN_EMPTY_BODY = YES;
271 | CLANG_WARN_ENUM_CONVERSION = YES;
272 | CLANG_WARN_INFINITE_RECURSION = YES;
273 | CLANG_WARN_INT_CONVERSION = YES;
274 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
275 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
276 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
278 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
279 | CLANG_WARN_STRICT_PROTOTYPES = YES;
280 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
281 | CLANG_WARN_UNREACHABLE_CODE = YES;
282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
283 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
284 | COPY_PHASE_STRIP = NO;
285 | DEBUG_INFORMATION_FORMAT = dwarf;
286 | ENABLE_STRICT_OBJC_MSGSEND = YES;
287 | ENABLE_TESTABILITY = YES;
288 | GCC_C_LANGUAGE_STANDARD = gnu99;
289 | GCC_DYNAMIC_NO_PIC = NO;
290 | GCC_NO_COMMON_BLOCKS = YES;
291 | GCC_OPTIMIZATION_LEVEL = 0;
292 | GCC_PREPROCESSOR_DEFINITIONS = (
293 | "DEBUG=1",
294 | "$(inherited)",
295 | );
296 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
297 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
298 | GCC_WARN_UNDECLARED_SELECTOR = YES;
299 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
300 | GCC_WARN_UNUSED_FUNCTION = YES;
301 | GCC_WARN_UNUSED_VARIABLE = YES;
302 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
303 | MTL_ENABLE_DEBUG_INFO = YES;
304 | ONLY_ACTIVE_ARCH = YES;
305 | SDKROOT = iphoneos;
306 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
307 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
308 | TARGETED_DEVICE_FAMILY = "1,2";
309 | };
310 | name = Debug;
311 | };
312 | 8EC8C46C1DED83D10044FB44 /* Release */ = {
313 | isa = XCBuildConfiguration;
314 | buildSettings = {
315 | ALWAYS_SEARCH_USER_PATHS = NO;
316 | CLANG_ANALYZER_NONNULL = YES;
317 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
318 | CLANG_CXX_LIBRARY = "libc++";
319 | CLANG_ENABLE_MODULES = YES;
320 | CLANG_ENABLE_OBJC_ARC = YES;
321 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
322 | CLANG_WARN_BOOL_CONVERSION = YES;
323 | CLANG_WARN_COMMA = YES;
324 | CLANG_WARN_CONSTANT_CONVERSION = YES;
325 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
326 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
327 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
328 | CLANG_WARN_EMPTY_BODY = YES;
329 | CLANG_WARN_ENUM_CONVERSION = YES;
330 | CLANG_WARN_INFINITE_RECURSION = YES;
331 | CLANG_WARN_INT_CONVERSION = YES;
332 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
333 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
334 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
335 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
336 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
337 | CLANG_WARN_STRICT_PROTOTYPES = YES;
338 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
339 | CLANG_WARN_UNREACHABLE_CODE = YES;
340 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
341 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
342 | COPY_PHASE_STRIP = NO;
343 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
344 | ENABLE_NS_ASSERTIONS = NO;
345 | ENABLE_STRICT_OBJC_MSGSEND = YES;
346 | GCC_C_LANGUAGE_STANDARD = gnu99;
347 | GCC_NO_COMMON_BLOCKS = YES;
348 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
349 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
350 | GCC_WARN_UNDECLARED_SELECTOR = YES;
351 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
352 | GCC_WARN_UNUSED_FUNCTION = YES;
353 | GCC_WARN_UNUSED_VARIABLE = YES;
354 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
355 | MTL_ENABLE_DEBUG_INFO = NO;
356 | SDKROOT = iphoneos;
357 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
358 | TARGETED_DEVICE_FAMILY = "1,2";
359 | VALIDATE_PRODUCT = YES;
360 | };
361 | name = Release;
362 | };
363 | 8EC8C46E1DED83D10044FB44 /* Debug */ = {
364 | isa = XCBuildConfiguration;
365 | baseConfigurationReference = 1BA2AAEE0DEE33072083F3FD /* Pods-Demo.debug.xcconfig */;
366 | buildSettings = {
367 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
368 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
369 | DEVELOPMENT_TEAM = 683U48NZTT;
370 | INFOPLIST_FILE = Demo/Info.plist;
371 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
372 | PRODUCT_BUNDLE_IDENTIFIER = com.orazz.Demo;
373 | PRODUCT_NAME = "$(TARGET_NAME)";
374 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
375 | SWIFT_VERSION = 4.2;
376 | };
377 | name = Debug;
378 | };
379 | 8EC8C46F1DED83D10044FB44 /* Release */ = {
380 | isa = XCBuildConfiguration;
381 | baseConfigurationReference = CBFCE409C80D5996E69369E9 /* Pods-Demo.release.xcconfig */;
382 | buildSettings = {
383 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
384 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
385 | DEVELOPMENT_TEAM = 683U48NZTT;
386 | INFOPLIST_FILE = Demo/Info.plist;
387 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
388 | PRODUCT_BUNDLE_IDENTIFIER = com.orazz.Demo;
389 | PRODUCT_NAME = "$(TARGET_NAME)";
390 | SWIFT_SWIFT3_OBJC_INFERENCE = Default;
391 | SWIFT_VERSION = 4.2;
392 | };
393 | name = Release;
394 | };
395 | /* End XCBuildConfiguration section */
396 |
397 | /* Begin XCConfigurationList section */
398 | 8EC8C4561DED83D10044FB44 /* Build configuration list for PBXProject "Demo" */ = {
399 | isa = XCConfigurationList;
400 | buildConfigurations = (
401 | 8EC8C46B1DED83D10044FB44 /* Debug */,
402 | 8EC8C46C1DED83D10044FB44 /* Release */,
403 | );
404 | defaultConfigurationIsVisible = 0;
405 | defaultConfigurationName = Release;
406 | };
407 | 8EC8C46D1DED83D10044FB44 /* Build configuration list for PBXNativeTarget "Demo" */ = {
408 | isa = XCConfigurationList;
409 | buildConfigurations = (
410 | 8EC8C46E1DED83D10044FB44 /* Debug */,
411 | 8EC8C46F1DED83D10044FB44 /* Release */,
412 | );
413 | defaultConfigurationIsVisible = 0;
414 | defaultConfigurationName = Release;
415 | };
416 | /* End XCConfigurationList section */
417 | };
418 | rootObject = 8EC8C4531DED83D10044FB44 /* Project object */;
419 | }
420 |
--------------------------------------------------------------------------------
/Example/Demo1-not library/CreditCardForm/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // CreditCardForum
4 | //
5 | // Created by Atakishiyev Orazdurdy on 11/5/16.
6 | // Copyright © 2016 Veriloft. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Stripe
11 | import AKMaskField
12 | import CreditCardValidator
13 |
14 | public enum Brands : String {
15 | case NONE, Visa, MasterCard, Amex, JCB, DEFAULT, Discover
16 | }
17 |
18 | class ViewController: UIViewController, STPPaymentCardTextFieldDelegate {
19 |
20 | let paymentTextField = STPPaymentCardTextField()
21 | var cardView: UIView!
22 | var backImage: UIImageView!
23 | var imageView: UIImageView!
24 |
25 | var cardNumber:AKMaskField!
26 | var cardHolder:UILabel!
27 | var fullname:UILabel!
28 | var expireDate: AKMaskField!
29 | var expireDateText: UILabel!
30 | var backView: UIView!
31 | var frontView: UIView!
32 | var backLine: UIView!
33 | var cvc: AKMaskField!
34 | var chipImg: UIImageView!
35 |
36 | var showingBack = false
37 | var gradientLayer: CAGradientLayer!
38 |
39 | var colors = [String : [UIColor]]()
40 |
41 | override func viewDidLoad() {
42 | super.viewDidLoad()
43 |
44 | colors[Brands.NONE.rawValue] = [UIColor.hexStr(hexStr: "#363434", alpha: 1), UIColor.hexStr(hexStr: "#363434", alpha: 1)]
45 | colors[Brands.Visa.rawValue] = [UIColor.hexStr(hexStr: "#5D8BF2", alpha: 1), UIColor.hexStr(hexStr: "#3545AE", alpha: 1)]
46 | colors[Brands.MasterCard.rawValue] = [UIColor.hexStr(hexStr: "#ED495A", alpha: 1), UIColor.hexStr(hexStr: "#8B1A2B", alpha: 1)]
47 | colors[Brands.Amex.rawValue] = [UIColor.hexStr(hexStr: "#005B9D", alpha: 1), UIColor.hexStr(hexStr: "#132972", alpha: 1)]
48 | colors[Brands.JCB.rawValue] = [UIColor.hexStr(hexStr: "#265797", alpha: 1), UIColor.hexStr(hexStr: "#3d6eaa", alpha: 1)]
49 | colors["Diners Club"] = [UIColor.hexStr(hexStr: "#5b99d8", alpha: 1), UIColor.hexStr(hexStr: "#4186CD", alpha: 1)]
50 | colors[Brands.Discover.rawValue] = [UIColor.hexStr(hexStr: "#e8a258", alpha: 1), UIColor.hexStr(hexStr: "#D97B16", alpha: 1)]
51 | colors[Brands.DEFAULT.rawValue] = [UIColor.hexStr(hexStr: "#5D8BF2", alpha: 1), UIColor.hexStr(hexStr: "#3545AE", alpha: 1)]
52 |
53 | createCard()
54 |
55 | paymentTextField.frame = CGRect(x: 15, y: 199, width: self.view.frame.size.width - 30, height: 44)
56 | paymentTextField.delegate = self
57 | paymentTextField.translatesAutoresizingMaskIntoConstraints = false
58 | paymentTextField.borderWidth = 0
59 |
60 | let border = CALayer()
61 | let width = CGFloat(1.0)
62 | border.borderColor = UIColor.darkGray.cgColor
63 | border.frame = CGRect(x: 0, y: paymentTextField.frame.size.height - width, width: paymentTextField.frame.size.width, height: paymentTextField.frame.size.height)
64 | border.borderWidth = width
65 | paymentTextField.layer.addSublayer(border)
66 | paymentTextField.layer.masksToBounds = true
67 |
68 | view.addSubview(paymentTextField)
69 |
70 | let top = paymentTextField.topAnchor.constraint(equalTo: cardView.bottomAnchor, constant: 20)
71 | let horizontalConstraint = paymentTextField.centerXAnchor.constraint(equalTo: view.centerXAnchor)
72 | let widthConstraint = paymentTextField.widthAnchor.constraint(equalToConstant: self.view.frame.size.width-20)
73 | let heightConstraint = paymentTextField.heightAnchor.constraint(equalToConstant: 44)
74 |
75 | NSLayoutConstraint.activate([top, widthConstraint, heightConstraint, horizontalConstraint])
76 | }
77 |
78 | func setGradientBackground(v: UIView, top: CGColor, bottom: CGColor) {
79 | let colorTop = top
80 | let colorBottom = bottom
81 |
82 | gradientLayer = CAGradientLayer()
83 | gradientLayer.colors = [ colorTop, colorBottom]
84 | gradientLayer.locations = [ 0.0, 1.0]
85 | gradientLayer.frame = v.bounds
86 | backView.backgroundColor = UIColor.hexStr(hexStr: "#363434", alpha: 1)
87 | v.layer.addSublayer(gradientLayer)
88 | }
89 |
90 | func createCard() {
91 | let frame = self.view.frame
92 | cardView = UIView(frame: CGRect(x: (frame.size.width - 300)/2, y: 64, width: 300, height: 200))
93 | cardView.translatesAutoresizingMaskIntoConstraints = false
94 | cardView.layer.cornerRadius = 6
95 | cardView.backgroundColor = .red
96 |
97 | backView = UIView(frame: CGRect(x: (frame.size.width - 300)/2, y: 64, width: 300, height: 200))
98 | backView.translatesAutoresizingMaskIntoConstraints = false
99 | backView.layer.cornerRadius = 6
100 | backView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
101 | backView.autoresizingMask = [UIViewAutoresizing.flexibleLeftMargin, UIViewAutoresizing.flexibleRightMargin, UIViewAutoresizing.flexibleTopMargin, UIViewAutoresizing.flexibleBottomMargin]
102 |
103 | frontView = UIView(frame: CGRect(x: (frame.size.width - 300)/2, y: 64, width: 300, height: 200))
104 | frontView.translatesAutoresizingMaskIntoConstraints = false
105 | frontView.layer.cornerRadius = 6
106 | frontView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
107 | frontView.autoresizingMask = [UIViewAutoresizing.flexibleLeftMargin, UIViewAutoresizing.flexibleRightMargin, UIViewAutoresizing.flexibleTopMargin, UIViewAutoresizing.flexibleBottomMargin]
108 |
109 | backImage = UIImageView(frame: CGRect.zero)
110 | backImage.translatesAutoresizingMaskIntoConstraints = false
111 | backImage.image = UIImage(named: "back.jpg")
112 | backImage.contentMode = UIViewContentMode.scaleAspectFill
113 |
114 | //Card brand image
115 | imageView = UIImageView(frame: CGRect.zero)
116 | imageView.translatesAutoresizingMaskIntoConstraints = false
117 | imageView.contentMode = UIViewContentMode.scaleAspectFit
118 |
119 | //Credit card number
120 | cardNumber = AKMaskField()
121 | cardNumber.translatesAutoresizingMaskIntoConstraints = false
122 | cardNumber.maskExpression = "{....} {....} {....} {....}"
123 | //cardNumber.text = "XXXXXXXXXXXXXXXX"
124 | cardNumber.textColor = .white
125 | cardNumber.isUserInteractionEnabled = false
126 | cardNumber.textAlignment = NSTextAlignment.center
127 | cardNumber.font = UIFont(name: "Helvetica Neue", size: 20)
128 |
129 | //Card holder uilabel
130 | cardHolder = UILabel(frame: CGRect.zero)
131 | cardHolder.translatesAutoresizingMaskIntoConstraints = false
132 | cardHolder.font = UIFont(name: "Helvetica Neue", size: 10)
133 | cardHolder.text = "CARD HOLDER"
134 | cardHolder.textColor = UIColor.hexStr(hexStr: "#bdc3c7", alpha: 1)
135 |
136 | //Name
137 | fullname = UILabel(frame: CGRect.zero)
138 | fullname.translatesAutoresizingMaskIntoConstraints = false
139 | fullname.font = UIFont(name: "Helvetica Neue", size: 12)
140 | fullname.text = "Atakishi Oraz"
141 | fullname.textColor = .white
142 |
143 | //Expire Date
144 | expireDate = AKMaskField()
145 | expireDate.translatesAutoresizingMaskIntoConstraints = false
146 | expireDate.font = UIFont(name: "Helvetica Neue", size: 12)
147 | expireDate.maskExpression = "{..}/{..}"
148 | expireDate.text = paymentTextField.expirationPlaceholder
149 | expireDate.textColor = .white
150 |
151 | //Expire Date Text
152 | expireDateText = UILabel(frame: CGRect.zero)
153 | expireDateText.translatesAutoresizingMaskIntoConstraints = false
154 | expireDateText.font = UIFont(name: "Helvetica Neue", size: 10)
155 | expireDateText.text = "EXPIRY"
156 | expireDateText.textColor = UIColor.hexStr(hexStr: "#bdc3c7", alpha: 1)
157 |
158 | //BackLine
159 | backLine = UIView(frame: CGRect.zero)
160 | backLine.translatesAutoresizingMaskIntoConstraints = false
161 | backLine.backgroundColor = .black
162 |
163 | //CVC textfield
164 | cvc = AKMaskField()
165 | cvc.translatesAutoresizingMaskIntoConstraints = false
166 | cvc.maskExpression = "..."
167 | cvc.text = paymentTextField.cvc
168 | cvc.backgroundColor = .white
169 | cvc.textAlignment = NSTextAlignment.center
170 | cvc.isUserInteractionEnabled = false
171 |
172 | //Chip image
173 | chipImg = UIImageView(frame: CGRect.zero)
174 | chipImg.image = UIImage(named: "chip")
175 | chipImg.translatesAutoresizingMaskIntoConstraints = false
176 | chipImg.alpha = 0.5
177 |
178 | frontView.isHidden = false
179 | backView.isHidden = true
180 |
181 | cardView.clipsToBounds = true
182 | //frontView.addSubview(backImage)
183 | cardView.addSubview(frontView)
184 |
185 | setGradientBackground(v: frontView, top: UIColor.hexStr(hexStr: "#363434", alpha: 1).cgColor, bottom: UIColor.hexStr(hexStr: "#363434", alpha: 1).cgColor)
186 |
187 | frontView.addSubview(imageView)
188 | frontView.addSubview(cardHolder)
189 | frontView.addSubview(fullname)
190 | frontView.addSubview(cardNumber)
191 | frontView.addSubview(expireDate)
192 | frontView.addSubview(expireDateText)
193 | frontView.addSubview(chipImg)
194 |
195 | backView.addSubview(backLine)
196 | backView.addSubview(cvc)
197 | cardView.addSubview(backView)
198 | view.addSubview(cardView)
199 |
200 | //CardView
201 | let top = cardView.topAnchor.constraint(equalTo: view.topAnchor, constant: 64)
202 | let horizontalConstraint = cardView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
203 | let widthConstraint = cardView.widthAnchor.constraint(equalToConstant: 300)
204 | let heightConstraint = cardView.heightAnchor.constraint(equalToConstant: 170)
205 | NSLayoutConstraint.activate([top, widthConstraint, heightConstraint, horizontalConstraint])
206 |
207 | //Back View
208 | let frontViewtop = frontView.topAnchor.constraint(equalTo: view.topAnchor, constant: 64)
209 | let frontViewhorizontalConstraint = frontView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
210 | let frontViewwidthConstraint = frontView.widthAnchor.constraint(equalToConstant: 300)
211 | let frontViewheightConstraint = frontView.heightAnchor.constraint(equalToConstant: 170)
212 | NSLayoutConstraint.activate([frontViewtop, frontViewhorizontalConstraint, frontViewwidthConstraint, frontViewheightConstraint])
213 |
214 | //Back View
215 | let cardBacktop = backView.topAnchor.constraint(equalTo: view.topAnchor, constant: 64)
216 | let cardBackhorizontalConstraint = backView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
217 | let cardBackwidthConstraint = backView.widthAnchor.constraint(equalToConstant: 300)
218 | let cardBackheightConstraint = backView.heightAnchor.constraint(equalToConstant: 170)
219 | NSLayoutConstraint.activate([cardBacktop, cardBackhorizontalConstraint, cardBackwidthConstraint, cardBackheightConstraint])
220 |
221 | // //Background imageview
222 | // let backImgTop = backImage.topAnchor.constraint(equalTo: cardView.topAnchor)
223 | // let leadingCont = backImage.leadingAnchor.constraint(equalTo: cardView.leadingAnchor)
224 | // let trailingCont = backImage.trailingAnchor.constraint(equalTo: cardView.trailingAnchor)
225 | // let bottomCont = backImage.bottomAnchor.constraint(equalTo: cardView.bottomAnchor)
226 | // NSLayoutConstraint.activate([backImgTop, leadingCont, trailingCont, bottomCont])
227 |
228 | //Card brand imageview
229 | let top1 = imageView.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 10)
230 | let trailing = imageView.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -10)
231 | let widthConstraint1 = imageView.widthAnchor.constraint(equalToConstant: 60)
232 | let heightConstraint1 = imageView.heightAnchor.constraint(equalToConstant: 40)
233 | NSLayoutConstraint.activate([top1, trailing, widthConstraint1, heightConstraint1])
234 |
235 | //Card number
236 | let horizontalConstraintcardNumber = cardNumber.centerXAnchor.constraint(equalTo: cardView.centerXAnchor)
237 | let verticalConstraintcardNumber = cardNumber.centerYAnchor.constraint(equalTo: cardView.centerYAnchor)
238 | let widthConstraintcardNumber = cardNumber.widthAnchor.constraint(equalToConstant: 200)
239 | let heightConstraintcardNumber = cardNumber.heightAnchor.constraint(equalToConstant: 30)
240 | NSLayoutConstraint.activate([widthConstraintcardNumber, verticalConstraintcardNumber, heightConstraintcardNumber, horizontalConstraintcardNumber])
241 |
242 | //Name
243 | let fullnameBottom = fullname.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: -20)
244 | let fullnameleadingCont = fullname.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 15)
245 | NSLayoutConstraint.activate([fullnameBottom, fullnameleadingCont])
246 |
247 | //Card Holder
248 | let cardHolderTop = cardHolder.bottomAnchor.constraint(equalTo: fullname.topAnchor, constant: -3)
249 | let cardHolderleadingCont = cardHolder.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 15)
250 | NSLayoutConstraint.activate([cardHolderTop, cardHolderleadingCont])
251 |
252 | //Expire Date
253 | let expireDateBottom = expireDate.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: -20)
254 | let expireDateleadingCont = expireDate.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -55)
255 | NSLayoutConstraint.activate([expireDateBottom, expireDateleadingCont])
256 |
257 | //Expire Date Text
258 | let expireDateTextBottom = expireDateText.bottomAnchor.constraint(equalTo: expireDate.topAnchor, constant: -3)
259 | let expireDateTextLeadingCont = expireDateText.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -58)
260 | NSLayoutConstraint.activate([expireDateTextBottom, expireDateTextLeadingCont])
261 |
262 | let chipImgtop = chipImg.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 15)
263 | let chipImgtrailing = chipImg.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 15)
264 | let chipImgwidthConstraint = chipImg.widthAnchor.constraint(equalToConstant: 45)
265 | let chipImgheightConstraint = chipImg.heightAnchor.constraint(equalToConstant: 30)
266 | NSLayoutConstraint.activate([chipImgtop, chipImgtrailing, chipImgwidthConstraint, chipImgheightConstraint])
267 |
268 | //Back Line
269 | let backLinetop = backLine.topAnchor.constraint(equalTo: backView.topAnchor, constant: 20)
270 | let backLinehorizontalConstraint = backLine.centerXAnchor.constraint(equalTo: backView.centerXAnchor)
271 | let backLinewidthConstraint = backLine.widthAnchor.constraint(equalToConstant: 300)
272 | let backLineheightConstraint = backLine.heightAnchor.constraint(equalToConstant: 50)
273 | NSLayoutConstraint.activate([backLinetop, backLinehorizontalConstraint, backLinewidthConstraint, backLineheightConstraint])
274 |
275 | //cvc
276 | let cvcTop = cvc.topAnchor.constraint(equalTo: backLine.bottomAnchor, constant: 10)
277 | let cvcwidthConstraint = cvc.widthAnchor.constraint(equalToConstant: 50)
278 | let cvcheightConstraint = cvc.heightAnchor.constraint(equalToConstant: 25)
279 | let trailingCVC = cvc.trailingAnchor.constraint(equalTo: backView.trailingAnchor, constant: -10)
280 | NSLayoutConstraint.activate([cvcTop, cvcwidthConstraint, cvcheightConstraint, trailingCVC])
281 | }
282 |
283 | func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) {
284 | self.cardNumber.text = textField.cardNumber
285 |
286 | self.expireDate.text = NSString(format: "%02ld", textField.expirationMonth) as String + "/" + (NSString(format: "%02ld", textField.expirationYear) as String)
287 |
288 | if textField.expirationMonth == 0 {
289 | expireDate.text = "MM/YY"
290 | }
291 | let v = CreditCardValidator()
292 | self.cvc.text = textField.cvc
293 |
294 | if (textField.cardNumber?.characters.count)! >= 7 || (textField.cardNumber?.characters.count)! < 4 {
295 |
296 | guard let type = v.type(from: "\(textField.cardNumber!)") else {
297 | self.imageView.image = nil
298 | if let name = colors["NONE"] {
299 | setType(colors: [name[0].cgColor, name[1].cgColor], alpha: 0.5, back: name[0])
300 | }
301 | return
302 | }
303 |
304 | // Visa, Mastercard, Amex etc.
305 | if let name = colors[type.name] {
306 | self.imageView.image = UIImage(named: type.name)
307 | setType(colors: [name[0].cgColor, name[1].cgColor], alpha: 1, back: name[0])
308 | }else{
309 | setType(colors: [self.colors["DEFAULT"]![0].cgColor, self.colors["DEFAULT"]![0].cgColor], alpha: 1, back: self.colors["DEFAULT"]![0])
310 | }
311 | }
312 | }
313 |
314 | func setType(colors: [CGColor], alpha: CGFloat, back: UIColor) {
315 | UIView.animate(withDuration: 2, animations: { () -> Void in
316 | self.gradientLayer.colors = colors
317 | })
318 | self.backView.backgroundColor = back
319 | self.chipImg.alpha = alpha
320 | }
321 |
322 | func paymentCardTextFieldDidEndEditingExpiration(_ textField: STPPaymentCardTextField) {
323 |
324 | if "\(textField.expirationYear)".characters.count <= 1 {
325 | expireDate.text = "MM/YY"
326 | }
327 | }
328 |
329 | func paymentCardTextFieldDidBeginEditingExpiration(_ textField: STPPaymentCardTextField) {
330 |
331 | }
332 |
333 | func paymentCardTextFieldDidBeginEditingCVC(_ textField: STPPaymentCardTextField) {
334 | if !showingBack {
335 | flip()
336 | showingBack = true
337 | }
338 | }
339 |
340 | func paymentCardTextFieldDidEndEditingCVC(_ textField: STPPaymentCardTextField) {
341 | if showingBack {
342 | flip()
343 | showingBack = false
344 | }
345 | }
346 |
347 | func flip() {
348 | var showingSide = frontView
349 | var hiddenSide = backView
350 | if showingBack {
351 | (showingSide, hiddenSide) = (backView, frontView)
352 | }
353 |
354 | UIView.transition(from:showingSide!,
355 | to: hiddenSide!,
356 | duration: 0.7,
357 | options: [UIViewAnimationOptions.transitionFlipFromRight, UIViewAnimationOptions.showHideTransitionViews],
358 | completion: nil)
359 |
360 | }
361 |
362 | }
363 |
364 | extension UIColor {
365 | class func hexStr ( hexStr : NSString, alpha : CGFloat) -> UIColor {
366 | let hexStr = hexStr.replacingOccurrences(of: "#", with: "")
367 | let scanner = Scanner(string: hexStr as String)
368 | var color: UInt32 = 0
369 | if scanner.scanHexInt32(&color) {
370 | let r = CGFloat((color & 0xFF0000) >> 16) / 255.0
371 | let g = CGFloat((color & 0x00FF00) >> 8) / 255.0
372 | let b = CGFloat(color & 0x0000FF) / 255.0
373 | return UIColor(red:r,green:g,blue:b,alpha:alpha)
374 | } else {
375 | print("invalid hex string", terminator: "")
376 | return UIColor.white;
377 | }
378 | }
379 | }
380 |
381 |
--------------------------------------------------------------------------------
/CreditCardForm/Classes/AKMaskField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AKMaskField.swift
3 | // AKMaskField
4 | // GitHub: https://github.com/artemkrachulov/AKMaskField
5 | //
6 | // Created by Artem Krachulov
7 | // Copyright (c) 2016 Artem Krachulov. All rights reserved.
8 | // Website: http://www.artemkrachulov.com/
9 | //
10 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
11 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
12 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
13 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in all copies or
17 | // substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
20 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
21 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
22 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 | // DEALINGS IN THE SOFTWARE.
25 | //
26 | // v. 1.0
27 | //
28 |
29 | import UIKit
30 |
31 | /// AKMaskField is UITextField subclass which allows enter data in the fixed quantity
32 | /// and in the certain format (credit cards, telephone numbers, dates, etc.).
33 | /// You only need setup mask and mask template visible for the user.
34 | ///
35 | /// Example of usage (programmatically):
36 | ///
37 | /// ```
38 | /// var field = AKMaskField()
39 | /// field.setMask("{dddd}-{DDDD}-{WaWa}-{aaaa}", withMaskTemplate: "ABCD-EFGH-IJKL-MNOP")
40 | /// ```
41 | ///
42 | /// For more information click here [GitHub](https://github.com/artemkrachulov/AKMaskField)
43 | open class AKMaskField: UITextField {
44 |
45 | // MARK: - Configuring the Mask Field
46 |
47 | /// The string value that has blocks with pattern symbols that determine the certain format of input data. Wrap each mask block with proper bracket character.
48 | ///
49 | /// The predetermined formats (Mask symbol : Input format):
50 | ///
51 | /// - `d` : Number, decimal number from 0 to 9
52 | /// - `D` : Any symbol, except decimal number
53 | /// - `W` : Not an alphabetic symbol
54 | /// - `a` : Alphabetic symbol, a-Z
55 | /// - `.` : Corresponds to any symbol (default)
56 | ///
57 | /// Default value of this property is `nil`.
58 | @IBInspectable final public var maskExpression: String? {
59 | didSet {
60 |
61 | // - - - - - - - - - - - -
62 | // CHECKS
63 | // - - - - - - - - - - - -
64 |
65 | if guardMask { return }
66 |
67 | let brackets = AKMaskFieldUtility
68 | .matchesInString(maskExpression!,
69 | pattern: "(?<=\\\(maskBlockBrackets.left)).*?(?=\\\(maskBlockBrackets.right))")
70 |
71 | if brackets.isEmpty { return }
72 |
73 | // - - - - - - - - - - - -
74 | // SETUP
75 | // - - - - - - - - - - - -
76 |
77 | delegate = self
78 |
79 | maskTemplateText = maskExpression
80 |
81 | // - - - - - - - - - - - -
82 | // MASK OBJECT
83 | // - - - - - - - - - - - -
84 |
85 | maskBlocks = [AKMaskFieldBlock]()
86 |
87 | for (i, bracket) in brackets.enumerated() {
88 |
89 | // - - - - - - - - - - - - - - - -
90 | // Characters
91 |
92 | var characters = [AKMaskFieldBlockCharacter]()
93 |
94 | for y in 0.. (char: AKMaskFieldBlockCharacter, outsideBlock: Bool) {
282 |
283 | var nextBlockIndex: Int!
284 |
285 | var lowerBound = 0
286 | var upperBound = chars.count
287 |
288 | while lowerBound < upperBound {
289 |
290 | let midIndex = lowerBound + (upperBound - lowerBound) / 2
291 | let charLocation = chars[midIndex].templateRange.location
292 |
293 | if charLocation == location {
294 | return (chars[midIndex], false)
295 | } else if charLocation < location {
296 | lowerBound = midIndex + 1
297 | } else {
298 | upperBound = midIndex
299 | nextBlockIndex = midIndex
300 | }
301 | }
302 |
303 | return (chars[nextBlockIndex], true)
304 | }
305 |
306 | /// Check if current character match with pattern
307 | fileprivate func matchTextCharacter(_ textCharacter: Character, withMaskCharacter maskCharacter: AKMaskFieldBlockCharacter) -> Bool {
308 | return !AKMaskFieldUtility
309 | .matchesInString(String(textCharacter),
310 | pattern: maskCharacter.pattern.pattern()).isEmpty
311 | }
312 |
313 | fileprivate func updateMaskTemplateText() {
314 | AKMaskFieldUtility
315 | .replacingOccurrencesOfString(&maskTemplateText,
316 | target : "[\(maskBlockBrackets.left)\(maskBlockBrackets.right)]",
317 | withString : "")
318 |
319 | maskText = maskTemplateText
320 |
321 | refreshMask()
322 | }
323 |
324 | fileprivate func updateMaskTemplateTextFromBlock(_ index: Int) {
325 |
326 | AKMaskFieldUtility
327 | .replace(&maskTemplateText,
328 | withString : maskBlocks[index].template,
329 | inRange : maskBlocks[index].patternRange)
330 | }
331 |
332 | fileprivate struct AKMaskFieldProcessedBlock {
333 | var range : NSRange?
334 | var string : String = ""
335 | }
336 |
337 | fileprivate func moveCarret() {
338 | var position: Int
339 |
340 | switch maskStatus {
341 | case .clear : position = maskBlocks.first!.templateRange.location
342 | case .incomplete : position = maskBlocks.flatMap { $0.chars.filter { $0.status == .clear } }.first!.templateRange.location
343 | case .complete : position = Range(maskBlocks.last!.templateRange)!.upperBound
344 | }
345 |
346 | AKMaskFieldUtility.maskField(self, moveCaretToPosition: position)
347 | }
348 | }
349 | // MARK: - UITextFieldDelegate
350 |
351 | extension AKMaskField: UITextFieldDelegate {
352 |
353 | public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
354 | return maskDelegate?.maskFieldShouldBeginEditing(self) ?? true
355 | }
356 |
357 | public func textFieldDidBeginEditing(_ textField: UITextField) {
358 |
359 | maskDelegate?.maskFieldDidBeginEditing(self)
360 |
361 | if guardMask { return }
362 |
363 | moveCarret()
364 | }
365 |
366 | public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
367 | return maskDelegate?.maskFieldShouldEndEditing(self) ?? true
368 | }
369 |
370 | public func textFieldDidEndEditing(_ textField: UITextField) {
371 | maskDelegate?.maskFieldDidEndEditing(self)
372 | }
373 |
374 | public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
375 |
376 | // CHECKS
377 |
378 | if guardMask { return false }
379 |
380 | let maskBlocksChars = maskBlocks.flatMap { $0.chars }
381 |
382 | // EVENTS
383 |
384 | var event: AKMaskFieldEvent!
385 |
386 | var completed: Int = 0
387 | var cleared: Int = 0
388 |
389 | // PREPARE BLOCKS FOR USER PROCESSING
390 |
391 | var processedBlocks = [AKMaskFieldProcessedBlock]()
392 |
393 | // - - - - - - - - - - - -
394 | // STEP 1
395 | // Selected range
396 |
397 | // Find blocks with text which must be reset
398 |
399 | // a) Prepare an array with interserted ranges
400 |
401 | let intersertRanges = AKMaskFieldUtility
402 | .findIntersection(maskBlocks.map { return $0.templateRange }, withRange: range)
403 |
404 | // b) Create an array with interserted blocks
405 |
406 | for (i, intersertRange) in intersertRanges.enumerated() {
407 |
408 | var processedBlock = AKMaskFieldProcessedBlock()
409 | processedBlock.range = intersertRange
410 |
411 | if let intersertRange = intersertRange {
412 | processedBlock.range?.location = abs(maskBlocks[i].templateRange.location - intersertRange.location)
413 | }
414 | processedBlocks.append(processedBlock)
415 | }
416 |
417 | // - - - - - - - - - - - -
418 | // STEP 2
419 | // Replacement string
420 |
421 | var location = range.location
422 | var savedLocation = range.location
423 |
424 | for replacementCharacter in string {
425 | if location == maskText?.count { break }
426 |
427 | // Find next character
428 | // If character outside the block, jump to first character of the next block
429 | let nextCharacter = getNetCharacter(maskBlocksChars, fromLocation: location)
430 |
431 | var findMatches: Bool = false
432 |
433 | if nextCharacter.outsideBlock {
434 |
435 | // Check if replacement character match to mask template character in same location
436 |
437 | if replacementCharacter != Character(AKMaskFieldUtility.substring(maskTemplateText, withNSRange: NSMakeRange(location, 1))) &&
438 | replacementCharacter != " " {
439 |
440 | savedLocation = location
441 | findMatches = true
442 | }
443 | } else {
444 | findMatches = true
445 | }
446 |
447 | if findMatches {
448 | if matchTextCharacter(replacementCharacter, withMaskCharacter: nextCharacter.char) {
449 |
450 | location = nextCharacter.char.templateRange.location
451 | let blockIndex = nextCharacter.char.blockIndex
452 |
453 | processedBlocks[blockIndex].string.append(replacementCharacter)
454 |
455 | if processedBlocks[blockIndex].range == nil {
456 | processedBlocks[blockIndex].range = NSMakeRange(nextCharacter.char.index, 0)
457 | }
458 | } else {
459 |
460 | location = savedLocation
461 |
462 | event = .error
463 | break
464 | }
465 | }
466 |
467 | location += 1
468 | }
469 |
470 | // USER PROCESSING
471 |
472 | for (i, processedBlock) in processedBlocks.enumerated() {
473 | if var _range = processedBlock.range {
474 |
475 | // Prepare data
476 |
477 | var _string = processedBlock.string
478 |
479 | // Grab all changed data
480 | let shouldChangeBlock = maskDelegate?
481 | .maskField(self,
482 | shouldChangeBlock : maskBlocks[i],
483 | inRange : &_range,
484 | replacementString : &_string)
485 | ?? true
486 |
487 | if shouldChangeBlock {
488 |
489 | // REVALIDATE
490 |
491 | // - - - - - - - - - - - -
492 | // Selected range
493 |
494 | if processedBlock.range!.location != _range.location ||
495 | processedBlock.range!.length != _range.length {
496 |
497 | if let validatedRange = AKMaskFieldUtility
498 | .findIntersection([maskBlocks[i].templateRange], withRange: _range).first! as NSRange? {
499 |
500 | _range = validatedRange
501 | }
502 | }
503 |
504 | // - - - - - - - - - - - -
505 | // Replacement string
506 |
507 | if processedBlock.string != _string {
508 |
509 | var validatedString = ""
510 |
511 | // Start carret position
512 | var _location = _range.location
513 |
514 | for replacementCharacter in _string {
515 | if _location > maskBlocks[i].templateRange.length { break }
516 |
517 | if matchTextCharacter(replacementCharacter, withMaskCharacter: maskBlocks[i].chars[_location]) {
518 | validatedString.append(replacementCharacter)
519 | } else {
520 | event = .error
521 | break
522 | }
523 | _location += 1
524 | }
525 |
526 | _string = validatedString
527 | }
528 |
529 | // UPDATE MASK TEXT
530 |
531 | // - - - - - - - - - - - -
532 | // Replacement string
533 |
534 | if !_string.isEmpty {
535 |
536 | var maskTextRange = NSMakeRange(_range.location, _string.count)
537 |
538 | // Object
539 |
540 | for index in [Int](maskTextRange.location.. 0 {
571 |
572 | var maskTextRange = _range
573 |
574 | // Object
575 |
576 | for index in [Int](_range.location..<_range.location+_range.length) {
577 | maskBlocks[i].chars[index].status = .clear
578 | cleared += 1
579 | }
580 |
581 | // Mask text
582 |
583 | maskTextRange.location += maskBlocks[i].templateRange.location
584 |
585 | let cuttedTempalte = AKMaskFieldUtility
586 | .substring(maskTemplateText, withNSRange: maskTextRange)
587 |
588 | AKMaskFieldUtility
589 | .replace(&maskText,
590 | withString : cuttedTempalte,
591 | inRange : maskTextRange)
592 |
593 | }
594 | }
595 | }
596 | }
597 |
598 | // - - - - - - - - - - - -
599 | // DISPLAYED TEXT
600 | // - - - - - - - - - - - -
601 |
602 | refreshMask()
603 |
604 | AKMaskFieldUtility.maskField(self, moveCaretToPosition: location)
605 |
606 | // - - - - - - - - - - - -
607 | // EVENT
608 | // - - - - - - - - - - - -
609 |
610 | if completed != 0 {
611 | event = cleared == 0 ? .insert : .replace
612 | } else {
613 | if cleared != 0 {
614 | event = .delete
615 | }
616 | }
617 |
618 | if let event = event {
619 | maskDelegate?.maskField(self, didChangedWithEvent: event)
620 | }
621 |
622 | return false
623 | }
624 |
625 | public func textFieldShouldClear(_ textField: UITextField) -> Bool {
626 | text = nil
627 |
628 | return false
629 | }
630 |
631 | public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
632 | return maskDelegate?.maskFieldShouldReturn(self) ?? true
633 | }
634 |
635 | fileprivate func debugmaskBlocks() {
636 | for block in maskBlocks {
637 | print("BLOCK :")
638 | print("index : \(block.index)")
639 | print("status : \(block.status)")
640 | print("pattern : \(block.pattern)")
641 | print("patternRange : \(block.patternRange)")
642 | print("template : \(block.template)")
643 | print("templateRange : \(block.templateRange)")
644 | print("CHARS :")
645 | for char in block.chars {
646 | print(" index : \(char.index)")
647 | print(" blockIndex : \(char.blockIndex)")
648 | print(" status : \(char.status)")
649 | print(" pattern : \(String(describing: char.pattern))")
650 | print(" patternRange : \(char.patternRange)")
651 | print(" template : \(String(describing: char.template))")
652 | print(" templateRange : \(char.templateRange)")
653 | }
654 | print("")
655 | }
656 | }
657 | }
658 |
659 | // MARK: - AKMaskFieldDelegate
660 |
661 | protocol AKMaskFieldDelegate: class {
662 |
663 | /// Asks the delegate if editing should begin in the specified mask field.
664 | ///
665 | /// - parameter maskField : The mask field in which editing is about to begin.
666 | func maskFieldShouldBeginEditing(_ maskField: AKMaskField) -> Bool
667 |
668 | /// Asks the delegate if editing should begin in the specified mask field.
669 | ///
670 | /// - parameter maskField : The mask field in which editing is about to begin.
671 | func maskFieldDidBeginEditing(_ maskField: AKMaskField)
672 |
673 | /// Asks the delegate if editing should stop in the specified mask field.
674 | ///
675 | /// - parameter maskField : The mask field in which editing is about to end.
676 | func maskFieldShouldEndEditing(_ maskField: AKMaskField) -> Bool
677 |
678 | /// Tells the delegate that editing stopped for the specified mask field.
679 | ///
680 | /// - parameter maskField : The mask field for which editing ended.
681 | func maskFieldDidEndEditing(_ maskField: AKMaskField)
682 |
683 | /// Tells the delegate that specified mask field change text with event.
684 | ///
685 | /// - parameter maskField : The mask field for which event changed.
686 | /// - parameter event : Event constant value received after manipulations.
687 | func maskField(_ maskField: AKMaskField, didChangedWithEvent event: AKMaskFieldEvent)
688 |
689 | /// Asks the delegate if the specified mask block should be changed.
690 | ///
691 | /// - parameter maskField : The mask field containing the text.
692 | /// - parameter block : Target block
693 | /// - parameter range : The range of characters to be replaced (inout parameter).
694 | /// - parameter string : The replacement string for the specified range (inout parameter).
695 | func maskField(_ maskField: AKMaskField, shouldChangeBlock block: AKMaskFieldBlock, inRange range: inout NSRange, replacementString string: inout String) -> Bool
696 |
697 | /// Asks the delegate if the mask field should process the pressing of the return button.
698 | ///
699 | /// - parameter maskField : The mask field whose return button was pressed.
700 | func maskFieldShouldReturn(_ maskField: AKMaskField) -> Bool
701 | }
702 |
703 | extension AKMaskFieldDelegate {
704 | func maskFieldShouldBeginEditing(_ maskField: AKMaskField) -> Bool {
705 | return true
706 | }
707 | func maskFieldDidBeginEditing(_ maskField: AKMaskField) {}
708 | func maskFieldShouldEndEditing(_ maskField: AKMaskField) -> Bool {
709 | return true
710 | }
711 | func maskFieldDidEndEditing(_ maskField: AKMaskField) {}
712 | func maskField(_ maskField: AKMaskField, didChangedWithEvent event: AKMaskFieldEvent) {}
713 | func maskField(_ maskField: AKMaskField, shouldChangeBlock block: AKMaskFieldBlock, inRange range: inout NSRange, replacementString string: inout String) -> Bool {
714 | return true
715 | }
716 | func maskFieldShouldReturn(_ maskField: AKMaskField) -> Bool {
717 | return true
718 | }
719 | }
720 |
--------------------------------------------------------------------------------
/CreditCardForm.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 5639844A00E3E6E670C48111 /* Pods_CreditCardFormTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B58AD822FD99C8D36962BC8 /* Pods_CreditCardFormTests.framework */; };
11 | 8E1A520B1E7BF24500F02033 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 8E1A520A1E7BF24500F02033 /* LICENSE */; };
12 | 8E68F4E01E98C9690086D6F3 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 8EC8C50B1DEDC0420044FB44 /* README.md */; };
13 | 8EB6C7961DF93FD300225444 /* CreditCardForm.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 8EB6C7951DF93FD300225444 /* CreditCardForm.podspec */; };
14 | 8EC8C3D31DEC8C3E0044FB44 /* CreditCardForm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EC8C3C91DEC8C3E0044FB44 /* CreditCardForm.framework */; };
15 | 8EC8C3D81DEC8C3E0044FB44 /* CreditCardFormTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C3D71DEC8C3E0044FB44 /* CreditCardFormTests.swift */; };
16 | 8EC8C4F81DEDA1340044FB44 /* AKMaskField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4ED1DEDA1340044FB44 /* AKMaskField.swift */; };
17 | 8EC8C4F91DEDA1340044FB44 /* AKMaskFieldBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4EE1DEDA1340044FB44 /* AKMaskFieldBlock.swift */; };
18 | 8EC8C4FA1DEDA1340044FB44 /* AKMaskFieldBlockCharacter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4EF1DEDA1340044FB44 /* AKMaskFieldBlockCharacter.swift */; };
19 | 8EC8C4FB1DEDA1340044FB44 /* AKMaskFieldEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4F01DEDA1340044FB44 /* AKMaskFieldEvent.swift */; };
20 | 8EC8C4FC1DEDA1340044FB44 /* AKMaskFieldPatternCharacter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4F11DEDA1340044FB44 /* AKMaskFieldPatternCharacter.swift */; };
21 | 8EC8C4FD1DEDA1340044FB44 /* AKMaskFieldStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4F21DEDA1340044FB44 /* AKMaskFieldStatus.swift */; };
22 | 8EC8C4FE1DEDA1340044FB44 /* AKMaskFieldUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4F31DEDA1340044FB44 /* AKMaskFieldUtility.swift */; };
23 | 8EC8C4FF1DEDA1340044FB44 /* CreditCardFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4F41DEDA1340044FB44 /* CreditCardFormView.swift */; };
24 | 8EC8C5001DEDA1340044FB44 /* CreditCardValidationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4F51DEDA1340044FB44 /* CreditCardValidationType.swift */; };
25 | 8EC8C5011DEDA1340044FB44 /* CreditCardValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4F61DEDA1340044FB44 /* CreditCardValidator.swift */; };
26 | 8EC8C5021DEDA1340044FB44 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EC8C4F71DEDA1340044FB44 /* Utilities.swift */; };
27 | 8EC8C50A1DEDB5EA0044FB44 /* CreditCardForm.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EC8C5091DEDB5EA0044FB44 /* CreditCardForm.h */; settings = {ATTRIBUTES = (Public, ); }; };
28 | 8EFED2811E2796A6002BE8D5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8EFED2801E2796A6002BE8D5 /* Images.xcassets */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXContainerItemProxy section */
32 | 8EC8C3D41DEC8C3E0044FB44 /* PBXContainerItemProxy */ = {
33 | isa = PBXContainerItemProxy;
34 | containerPortal = 8EC8C3C01DEC8C3E0044FB44 /* Project object */;
35 | proxyType = 1;
36 | remoteGlobalIDString = 8EC8C3C81DEC8C3E0044FB44;
37 | remoteInfo = CreditCardForm;
38 | };
39 | /* End PBXContainerItemProxy section */
40 |
41 | /* Begin PBXFileReference section */
42 | 5B58AD822FD99C8D36962BC8 /* Pods_CreditCardFormTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CreditCardFormTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
43 | 8E1A520A1E7BF24500F02033 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; };
44 | 8EB6C7951DF93FD300225444 /* CreditCardForm.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CreditCardForm.podspec; sourceTree = SOURCE_ROOT; };
45 | 8EC8C3C91DEC8C3E0044FB44 /* CreditCardForm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CreditCardForm.framework; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 8EC8C3CD1DEC8C3E0044FB44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Info.plist; sourceTree = ""; };
47 | 8EC8C3D21DEC8C3E0044FB44 /* CreditCardFormTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CreditCardFormTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
48 | 8EC8C3D71DEC8C3E0044FB44 /* CreditCardFormTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditCardFormTests.swift; sourceTree = ""; };
49 | 8EC8C3D91DEC8C3E0044FB44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
50 | 8EC8C4ED1DEDA1340044FB44 /* AKMaskField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AKMaskField.swift; path = Classes/AKMaskField.swift; sourceTree = ""; };
51 | 8EC8C4EE1DEDA1340044FB44 /* AKMaskFieldBlock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AKMaskFieldBlock.swift; path = Classes/AKMaskFieldBlock.swift; sourceTree = ""; };
52 | 8EC8C4EF1DEDA1340044FB44 /* AKMaskFieldBlockCharacter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AKMaskFieldBlockCharacter.swift; path = Classes/AKMaskFieldBlockCharacter.swift; sourceTree = ""; };
53 | 8EC8C4F01DEDA1340044FB44 /* AKMaskFieldEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AKMaskFieldEvent.swift; path = Classes/AKMaskFieldEvent.swift; sourceTree = ""; };
54 | 8EC8C4F11DEDA1340044FB44 /* AKMaskFieldPatternCharacter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AKMaskFieldPatternCharacter.swift; path = Classes/AKMaskFieldPatternCharacter.swift; sourceTree = ""; };
55 | 8EC8C4F21DEDA1340044FB44 /* AKMaskFieldStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AKMaskFieldStatus.swift; path = Classes/AKMaskFieldStatus.swift; sourceTree = ""; };
56 | 8EC8C4F31DEDA1340044FB44 /* AKMaskFieldUtility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AKMaskFieldUtility.swift; path = Classes/AKMaskFieldUtility.swift; sourceTree = ""; };
57 | 8EC8C4F41DEDA1340044FB44 /* CreditCardFormView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CreditCardFormView.swift; path = Classes/CreditCardFormView.swift; sourceTree = ""; };
58 | 8EC8C4F51DEDA1340044FB44 /* CreditCardValidationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CreditCardValidationType.swift; path = Classes/CreditCardValidationType.swift; sourceTree = ""; };
59 | 8EC8C4F61DEDA1340044FB44 /* CreditCardValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CreditCardValidator.swift; path = Classes/CreditCardValidator.swift; sourceTree = ""; };
60 | 8EC8C4F71DEDA1340044FB44 /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Utilities.swift; path = Classes/Utilities.swift; sourceTree = ""; };
61 | 8EC8C5091DEDB5EA0044FB44 /* CreditCardForm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CreditCardForm.h; sourceTree = ""; };
62 | 8EC8C50B1DEDC0420044FB44 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; };
63 | 8EFED2801E2796A6002BE8D5 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
64 | ADEDAE40183C8D1AA2D6877F /* Pods_CreditCardForm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CreditCardForm.framework; sourceTree = BUILT_PRODUCTS_DIR; };
65 | /* End PBXFileReference section */
66 |
67 | /* Begin PBXFrameworksBuildPhase section */
68 | 8EC8C3C51DEC8C3E0044FB44 /* Frameworks */ = {
69 | isa = PBXFrameworksBuildPhase;
70 | buildActionMask = 2147483647;
71 | files = (
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | 8EC8C3CF1DEC8C3E0044FB44 /* Frameworks */ = {
76 | isa = PBXFrameworksBuildPhase;
77 | buildActionMask = 2147483647;
78 | files = (
79 | 8EC8C3D31DEC8C3E0044FB44 /* CreditCardForm.framework in Frameworks */,
80 | 5639844A00E3E6E670C48111 /* Pods_CreditCardFormTests.framework in Frameworks */,
81 | );
82 | runOnlyForDeploymentPostprocessing = 0;
83 | };
84 | /* End PBXFrameworksBuildPhase section */
85 |
86 | /* Begin PBXGroup section */
87 | 0C6147D0872EBEC9D5306BAC /* Pods */ = {
88 | isa = PBXGroup;
89 | children = (
90 | );
91 | name = Pods;
92 | sourceTree = "";
93 | };
94 | 8EC8C3BF1DEC8C3E0044FB44 = {
95 | isa = PBXGroup;
96 | children = (
97 | 8EC8C3CB1DEC8C3E0044FB44 /* CreditCardForm */,
98 | 8EC8C3D61DEC8C3E0044FB44 /* CreditCardFormTests */,
99 | 8EC8C3CA1DEC8C3E0044FB44 /* Products */,
100 | 0C6147D0872EBEC9D5306BAC /* Pods */,
101 | 8F926695DA4627EF2E17D452 /* Frameworks */,
102 | );
103 | sourceTree = "";
104 | };
105 | 8EC8C3CA1DEC8C3E0044FB44 /* Products */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 8EC8C3C91DEC8C3E0044FB44 /* CreditCardForm.framework */,
109 | 8EC8C3D21DEC8C3E0044FB44 /* CreditCardFormTests.xctest */,
110 | );
111 | name = Products;
112 | sourceTree = "";
113 | };
114 | 8EC8C3CB1DEC8C3E0044FB44 /* CreditCardForm */ = {
115 | isa = PBXGroup;
116 | children = (
117 | 8EC8C3CD1DEC8C3E0044FB44 /* Info.plist */,
118 | 8EC8C5091DEDB5EA0044FB44 /* CreditCardForm.h */,
119 | 8EC8C4ED1DEDA1340044FB44 /* AKMaskField.swift */,
120 | 8EC8C4EE1DEDA1340044FB44 /* AKMaskFieldBlock.swift */,
121 | 8EC8C4EF1DEDA1340044FB44 /* AKMaskFieldBlockCharacter.swift */,
122 | 8EC8C4F01DEDA1340044FB44 /* AKMaskFieldEvent.swift */,
123 | 8EC8C4F11DEDA1340044FB44 /* AKMaskFieldPatternCharacter.swift */,
124 | 8EC8C4F21DEDA1340044FB44 /* AKMaskFieldStatus.swift */,
125 | 8EC8C4F31DEDA1340044FB44 /* AKMaskFieldUtility.swift */,
126 | 8EC8C4F41DEDA1340044FB44 /* CreditCardFormView.swift */,
127 | 8EC8C4F51DEDA1340044FB44 /* CreditCardValidationType.swift */,
128 | 8EC8C4F61DEDA1340044FB44 /* CreditCardValidator.swift */,
129 | 8EC8C4F71DEDA1340044FB44 /* Utilities.swift */,
130 | 8EFED2801E2796A6002BE8D5 /* Images.xcassets */,
131 | 8E1A520A1E7BF24500F02033 /* LICENSE */,
132 | 8EC8C50B1DEDC0420044FB44 /* README.md */,
133 | 8EB6C7951DF93FD300225444 /* CreditCardForm.podspec */,
134 | );
135 | path = CreditCardForm;
136 | sourceTree = "";
137 | };
138 | 8EC8C3D61DEC8C3E0044FB44 /* CreditCardFormTests */ = {
139 | isa = PBXGroup;
140 | children = (
141 | 8EC8C3D71DEC8C3E0044FB44 /* CreditCardFormTests.swift */,
142 | 8EC8C3D91DEC8C3E0044FB44 /* Info.plist */,
143 | );
144 | path = CreditCardFormTests;
145 | sourceTree = "";
146 | };
147 | 8F926695DA4627EF2E17D452 /* Frameworks */ = {
148 | isa = PBXGroup;
149 | children = (
150 | ADEDAE40183C8D1AA2D6877F /* Pods_CreditCardForm.framework */,
151 | 5B58AD822FD99C8D36962BC8 /* Pods_CreditCardFormTests.framework */,
152 | );
153 | name = Frameworks;
154 | sourceTree = "";
155 | };
156 | /* End PBXGroup section */
157 |
158 | /* Begin PBXHeadersBuildPhase section */
159 | 8EC8C3C61DEC8C3E0044FB44 /* Headers */ = {
160 | isa = PBXHeadersBuildPhase;
161 | buildActionMask = 2147483647;
162 | files = (
163 | 8EC8C50A1DEDB5EA0044FB44 /* CreditCardForm.h in Headers */,
164 | );
165 | runOnlyForDeploymentPostprocessing = 0;
166 | };
167 | /* End PBXHeadersBuildPhase section */
168 |
169 | /* Begin PBXNativeTarget section */
170 | 8EC8C3C81DEC8C3E0044FB44 /* CreditCardForm */ = {
171 | isa = PBXNativeTarget;
172 | buildConfigurationList = 8EC8C3DD1DEC8C3E0044FB44 /* Build configuration list for PBXNativeTarget "CreditCardForm" */;
173 | buildPhases = (
174 | 8EC8C3C41DEC8C3E0044FB44 /* Sources */,
175 | 8EC8C3C51DEC8C3E0044FB44 /* Frameworks */,
176 | 8EC8C3C61DEC8C3E0044FB44 /* Headers */,
177 | 8EC8C3C71DEC8C3E0044FB44 /* Resources */,
178 | );
179 | buildRules = (
180 | );
181 | dependencies = (
182 | );
183 | name = CreditCardForm;
184 | productName = CreditCardForm;
185 | productReference = 8EC8C3C91DEC8C3E0044FB44 /* CreditCardForm.framework */;
186 | productType = "com.apple.product-type.framework";
187 | };
188 | 8EC8C3D11DEC8C3E0044FB44 /* CreditCardFormTests */ = {
189 | isa = PBXNativeTarget;
190 | buildConfigurationList = 8EC8C3E01DEC8C3E0044FB44 /* Build configuration list for PBXNativeTarget "CreditCardFormTests" */;
191 | buildPhases = (
192 | 45DD3926D0EAE4A137E80F4C /* [CP] Check Pods Manifest.lock */,
193 | 8EC8C3CE1DEC8C3E0044FB44 /* Sources */,
194 | 8EC8C3CF1DEC8C3E0044FB44 /* Frameworks */,
195 | 8EC8C3D01DEC8C3E0044FB44 /* Resources */,
196 | 26EB313D2B550B79F7269AFA /* [CP] Embed Pods Frameworks */,
197 | F758523A7CC3E083F529AB08 /* [CP] Copy Pods Resources */,
198 | );
199 | buildRules = (
200 | );
201 | dependencies = (
202 | 8EC8C3D51DEC8C3E0044FB44 /* PBXTargetDependency */,
203 | );
204 | name = CreditCardFormTests;
205 | productName = CreditCardFormTests;
206 | productReference = 8EC8C3D21DEC8C3E0044FB44 /* CreditCardFormTests.xctest */;
207 | productType = "com.apple.product-type.bundle.unit-test";
208 | };
209 | /* End PBXNativeTarget section */
210 |
211 | /* Begin PBXProject section */
212 | 8EC8C3C01DEC8C3E0044FB44 /* Project object */ = {
213 | isa = PBXProject;
214 | attributes = {
215 | LastSwiftUpdateCheck = 0820;
216 | LastUpgradeCheck = 1130;
217 | ORGANIZATIONNAME = Veriloft;
218 | TargetAttributes = {
219 | 8EC8C3C81DEC8C3E0044FB44 = {
220 | CreatedOnToolsVersion = 8.2;
221 | DevelopmentTeam = PRXV6FLQY4;
222 | LastSwiftMigration = 0820;
223 | ProvisioningStyle = Automatic;
224 | };
225 | 8EC8C3D11DEC8C3E0044FB44 = {
226 | CreatedOnToolsVersion = 8.2;
227 | DevelopmentTeam = 683U48NZTT;
228 | ProvisioningStyle = Automatic;
229 | };
230 | };
231 | };
232 | buildConfigurationList = 8EC8C3C31DEC8C3E0044FB44 /* Build configuration list for PBXProject "CreditCardForm" */;
233 | compatibilityVersion = "Xcode 3.2";
234 | developmentRegion = en;
235 | hasScannedForEncodings = 0;
236 | knownRegions = (
237 | en,
238 | Base,
239 | );
240 | mainGroup = 8EC8C3BF1DEC8C3E0044FB44;
241 | productRefGroup = 8EC8C3CA1DEC8C3E0044FB44 /* Products */;
242 | projectDirPath = "";
243 | projectRoot = "";
244 | targets = (
245 | 8EC8C3C81DEC8C3E0044FB44 /* CreditCardForm */,
246 | 8EC8C3D11DEC8C3E0044FB44 /* CreditCardFormTests */,
247 | );
248 | };
249 | /* End PBXProject section */
250 |
251 | /* Begin PBXResourcesBuildPhase section */
252 | 8EC8C3C71DEC8C3E0044FB44 /* Resources */ = {
253 | isa = PBXResourcesBuildPhase;
254 | buildActionMask = 2147483647;
255 | files = (
256 | 8E68F4E01E98C9690086D6F3 /* README.md in Resources */,
257 | 8E1A520B1E7BF24500F02033 /* LICENSE in Resources */,
258 | 8EFED2811E2796A6002BE8D5 /* Images.xcassets in Resources */,
259 | 8EB6C7961DF93FD300225444 /* CreditCardForm.podspec in Resources */,
260 | );
261 | runOnlyForDeploymentPostprocessing = 0;
262 | };
263 | 8EC8C3D01DEC8C3E0044FB44 /* Resources */ = {
264 | isa = PBXResourcesBuildPhase;
265 | buildActionMask = 2147483647;
266 | files = (
267 | );
268 | runOnlyForDeploymentPostprocessing = 0;
269 | };
270 | /* End PBXResourcesBuildPhase section */
271 |
272 | /* Begin PBXShellScriptBuildPhase section */
273 | 26EB313D2B550B79F7269AFA /* [CP] Embed Pods Frameworks */ = {
274 | isa = PBXShellScriptBuildPhase;
275 | buildActionMask = 2147483647;
276 | files = (
277 | );
278 | inputPaths = (
279 | );
280 | name = "[CP] Embed Pods Frameworks";
281 | outputPaths = (
282 | );
283 | runOnlyForDeploymentPostprocessing = 0;
284 | shellPath = /bin/sh;
285 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CreditCardFormTests/Pods-CreditCardFormTests-frameworks.sh\"\n";
286 | showEnvVarsInLog = 0;
287 | };
288 | 45DD3926D0EAE4A137E80F4C /* [CP] Check Pods Manifest.lock */ = {
289 | isa = PBXShellScriptBuildPhase;
290 | buildActionMask = 2147483647;
291 | files = (
292 | );
293 | inputPaths = (
294 | );
295 | name = "[CP] Check Pods Manifest.lock";
296 | outputPaths = (
297 | );
298 | runOnlyForDeploymentPostprocessing = 0;
299 | shellPath = /bin/sh;
300 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
301 | showEnvVarsInLog = 0;
302 | };
303 | F758523A7CC3E083F529AB08 /* [CP] Copy Pods Resources */ = {
304 | isa = PBXShellScriptBuildPhase;
305 | buildActionMask = 2147483647;
306 | files = (
307 | );
308 | inputPaths = (
309 | );
310 | name = "[CP] Copy Pods Resources";
311 | outputPaths = (
312 | );
313 | runOnlyForDeploymentPostprocessing = 0;
314 | shellPath = /bin/sh;
315 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CreditCardFormTests/Pods-CreditCardFormTests-resources.sh\"\n";
316 | showEnvVarsInLog = 0;
317 | };
318 | /* End PBXShellScriptBuildPhase section */
319 |
320 | /* Begin PBXSourcesBuildPhase section */
321 | 8EC8C3C41DEC8C3E0044FB44 /* Sources */ = {
322 | isa = PBXSourcesBuildPhase;
323 | buildActionMask = 2147483647;
324 | files = (
325 | 8EC8C5001DEDA1340044FB44 /* CreditCardValidationType.swift in Sources */,
326 | 8EC8C4F91DEDA1340044FB44 /* AKMaskFieldBlock.swift in Sources */,
327 | 8EC8C5021DEDA1340044FB44 /* Utilities.swift in Sources */,
328 | 8EC8C4F81DEDA1340044FB44 /* AKMaskField.swift in Sources */,
329 | 8EC8C5011DEDA1340044FB44 /* CreditCardValidator.swift in Sources */,
330 | 8EC8C4FA1DEDA1340044FB44 /* AKMaskFieldBlockCharacter.swift in Sources */,
331 | 8EC8C4FE1DEDA1340044FB44 /* AKMaskFieldUtility.swift in Sources */,
332 | 8EC8C4FC1DEDA1340044FB44 /* AKMaskFieldPatternCharacter.swift in Sources */,
333 | 8EC8C4FF1DEDA1340044FB44 /* CreditCardFormView.swift in Sources */,
334 | 8EC8C4FD1DEDA1340044FB44 /* AKMaskFieldStatus.swift in Sources */,
335 | 8EC8C4FB1DEDA1340044FB44 /* AKMaskFieldEvent.swift in Sources */,
336 | );
337 | runOnlyForDeploymentPostprocessing = 0;
338 | };
339 | 8EC8C3CE1DEC8C3E0044FB44 /* Sources */ = {
340 | isa = PBXSourcesBuildPhase;
341 | buildActionMask = 2147483647;
342 | files = (
343 | 8EC8C3D81DEC8C3E0044FB44 /* CreditCardFormTests.swift in Sources */,
344 | );
345 | runOnlyForDeploymentPostprocessing = 0;
346 | };
347 | /* End PBXSourcesBuildPhase section */
348 |
349 | /* Begin PBXTargetDependency section */
350 | 8EC8C3D51DEC8C3E0044FB44 /* PBXTargetDependency */ = {
351 | isa = PBXTargetDependency;
352 | target = 8EC8C3C81DEC8C3E0044FB44 /* CreditCardForm */;
353 | targetProxy = 8EC8C3D41DEC8C3E0044FB44 /* PBXContainerItemProxy */;
354 | };
355 | /* End PBXTargetDependency section */
356 |
357 | /* Begin XCBuildConfiguration section */
358 | 8EC8C3DB1DEC8C3E0044FB44 /* Debug */ = {
359 | isa = XCBuildConfiguration;
360 | buildSettings = {
361 | ALWAYS_SEARCH_USER_PATHS = NO;
362 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
363 | CLANG_ANALYZER_NONNULL = YES;
364 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
365 | CLANG_CXX_LIBRARY = "libc++";
366 | CLANG_ENABLE_MODULES = YES;
367 | CLANG_ENABLE_OBJC_ARC = YES;
368 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
369 | CLANG_WARN_BOOL_CONVERSION = YES;
370 | CLANG_WARN_COMMA = YES;
371 | CLANG_WARN_CONSTANT_CONVERSION = YES;
372 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
373 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
374 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
375 | CLANG_WARN_EMPTY_BODY = YES;
376 | CLANG_WARN_ENUM_CONVERSION = YES;
377 | CLANG_WARN_INFINITE_RECURSION = YES;
378 | CLANG_WARN_INT_CONVERSION = YES;
379 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
380 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
381 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
382 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
383 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
384 | CLANG_WARN_STRICT_PROTOTYPES = YES;
385 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
386 | CLANG_WARN_UNREACHABLE_CODE = YES;
387 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
388 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
389 | COPY_PHASE_STRIP = NO;
390 | CURRENT_PROJECT_VERSION = 1;
391 | DEBUG_INFORMATION_FORMAT = dwarf;
392 | ENABLE_STRICT_OBJC_MSGSEND = YES;
393 | ENABLE_TESTABILITY = YES;
394 | GCC_C_LANGUAGE_STANDARD = gnu99;
395 | GCC_DYNAMIC_NO_PIC = NO;
396 | GCC_NO_COMMON_BLOCKS = YES;
397 | GCC_OPTIMIZATION_LEVEL = 0;
398 | GCC_PREPROCESSOR_DEFINITIONS = (
399 | "DEBUG=1",
400 | "$(inherited)",
401 | );
402 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
403 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
404 | GCC_WARN_UNDECLARED_SELECTOR = YES;
405 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
406 | GCC_WARN_UNUSED_FUNCTION = YES;
407 | GCC_WARN_UNUSED_VARIABLE = YES;
408 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
409 | MTL_ENABLE_DEBUG_INFO = YES;
410 | ONLY_ACTIVE_ARCH = YES;
411 | SDKROOT = iphoneos;
412 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
413 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
414 | SWIFT_VERSION = 4.2;
415 | TARGETED_DEVICE_FAMILY = "1,2";
416 | VERSIONING_SYSTEM = "apple-generic";
417 | VERSION_INFO_PREFIX = "";
418 | };
419 | name = Debug;
420 | };
421 | 8EC8C3DC1DEC8C3E0044FB44 /* Release */ = {
422 | isa = XCBuildConfiguration;
423 | buildSettings = {
424 | ALWAYS_SEARCH_USER_PATHS = NO;
425 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
426 | CLANG_ANALYZER_NONNULL = YES;
427 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
428 | CLANG_CXX_LIBRARY = "libc++";
429 | CLANG_ENABLE_MODULES = YES;
430 | CLANG_ENABLE_OBJC_ARC = YES;
431 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
432 | CLANG_WARN_BOOL_CONVERSION = YES;
433 | CLANG_WARN_COMMA = YES;
434 | CLANG_WARN_CONSTANT_CONVERSION = YES;
435 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
436 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
437 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
438 | CLANG_WARN_EMPTY_BODY = YES;
439 | CLANG_WARN_ENUM_CONVERSION = YES;
440 | CLANG_WARN_INFINITE_RECURSION = YES;
441 | CLANG_WARN_INT_CONVERSION = YES;
442 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
443 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
444 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
445 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
446 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
447 | CLANG_WARN_STRICT_PROTOTYPES = YES;
448 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
449 | CLANG_WARN_UNREACHABLE_CODE = YES;
450 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
451 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
452 | COPY_PHASE_STRIP = NO;
453 | CURRENT_PROJECT_VERSION = 1;
454 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
455 | ENABLE_NS_ASSERTIONS = NO;
456 | ENABLE_STRICT_OBJC_MSGSEND = YES;
457 | GCC_C_LANGUAGE_STANDARD = gnu99;
458 | GCC_NO_COMMON_BLOCKS = YES;
459 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
460 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
461 | GCC_WARN_UNDECLARED_SELECTOR = YES;
462 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
463 | GCC_WARN_UNUSED_FUNCTION = YES;
464 | GCC_WARN_UNUSED_VARIABLE = YES;
465 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
466 | MTL_ENABLE_DEBUG_INFO = NO;
467 | SDKROOT = iphoneos;
468 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
469 | SWIFT_VERSION = 4.2;
470 | TARGETED_DEVICE_FAMILY = "1,2";
471 | VALIDATE_PRODUCT = YES;
472 | VERSIONING_SYSTEM = "apple-generic";
473 | VERSION_INFO_PREFIX = "";
474 | };
475 | name = Release;
476 | };
477 | 8EC8C3DE1DEC8C3E0044FB44 /* Debug */ = {
478 | isa = XCBuildConfiguration;
479 | buildSettings = {
480 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
481 | CLANG_ENABLE_MODULES = YES;
482 | CODE_SIGN_IDENTITY = "Apple Development";
483 | DEFINES_MODULE = YES;
484 | DEVELOPMENT_TEAM = PRXV6FLQY4;
485 | DYLIB_COMPATIBILITY_VERSION = 1;
486 | DYLIB_CURRENT_VERSION = 1;
487 | DYLIB_INSTALL_NAME_BASE = "@rpath";
488 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
489 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
490 | IPHONEOS_DEPLOYMENT_TARGET = 8.1;
491 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
492 | MARKETING_VERSION = 0.0.8;
493 | PRODUCT_BUNDLE_IDENTIFIER = com.orazz.CreditCardForm;
494 | PRODUCT_NAME = "$(TARGET_NAME)";
495 | SKIP_INSTALL = YES;
496 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
497 | SWIFT_VERSION = 5.0;
498 | };
499 | name = Debug;
500 | };
501 | 8EC8C3DF1DEC8C3E0044FB44 /* Release */ = {
502 | isa = XCBuildConfiguration;
503 | buildSettings = {
504 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
505 | CLANG_ENABLE_MODULES = YES;
506 | CODE_SIGN_IDENTITY = "Apple Development";
507 | DEFINES_MODULE = YES;
508 | DEVELOPMENT_TEAM = PRXV6FLQY4;
509 | DYLIB_COMPATIBILITY_VERSION = 1;
510 | DYLIB_CURRENT_VERSION = 1;
511 | DYLIB_INSTALL_NAME_BASE = "@rpath";
512 | INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
513 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
514 | IPHONEOS_DEPLOYMENT_TARGET = 8.1;
515 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
516 | MARKETING_VERSION = 0.0.8;
517 | PRODUCT_BUNDLE_IDENTIFIER = com.orazz.CreditCardForm;
518 | PRODUCT_NAME = "$(TARGET_NAME)";
519 | SKIP_INSTALL = YES;
520 | SWIFT_VERSION = 5.0;
521 | };
522 | name = Release;
523 | };
524 | 8EC8C3E11DEC8C3E0044FB44 /* Debug */ = {
525 | isa = XCBuildConfiguration;
526 | buildSettings = {
527 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
528 | DEVELOPMENT_TEAM = 683U48NZTT;
529 | INFOPLIST_FILE = CreditCardFormTests/Info.plist;
530 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
531 | PRODUCT_BUNDLE_IDENTIFIER = com.orazz.CreditCardFormTests;
532 | PRODUCT_NAME = "$(TARGET_NAME)";
533 | SWIFT_VERSION = 5.0;
534 | };
535 | name = Debug;
536 | };
537 | 8EC8C3E21DEC8C3E0044FB44 /* Release */ = {
538 | isa = XCBuildConfiguration;
539 | buildSettings = {
540 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
541 | DEVELOPMENT_TEAM = 683U48NZTT;
542 | INFOPLIST_FILE = CreditCardFormTests/Info.plist;
543 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
544 | PRODUCT_BUNDLE_IDENTIFIER = com.orazz.CreditCardFormTests;
545 | PRODUCT_NAME = "$(TARGET_NAME)";
546 | SWIFT_VERSION = 5.0;
547 | };
548 | name = Release;
549 | };
550 | /* End XCBuildConfiguration section */
551 |
552 | /* Begin XCConfigurationList section */
553 | 8EC8C3C31DEC8C3E0044FB44 /* Build configuration list for PBXProject "CreditCardForm" */ = {
554 | isa = XCConfigurationList;
555 | buildConfigurations = (
556 | 8EC8C3DB1DEC8C3E0044FB44 /* Debug */,
557 | 8EC8C3DC1DEC8C3E0044FB44 /* Release */,
558 | );
559 | defaultConfigurationIsVisible = 0;
560 | defaultConfigurationName = Release;
561 | };
562 | 8EC8C3DD1DEC8C3E0044FB44 /* Build configuration list for PBXNativeTarget "CreditCardForm" */ = {
563 | isa = XCConfigurationList;
564 | buildConfigurations = (
565 | 8EC8C3DE1DEC8C3E0044FB44 /* Debug */,
566 | 8EC8C3DF1DEC8C3E0044FB44 /* Release */,
567 | );
568 | defaultConfigurationIsVisible = 0;
569 | defaultConfigurationName = Release;
570 | };
571 | 8EC8C3E01DEC8C3E0044FB44 /* Build configuration list for PBXNativeTarget "CreditCardFormTests" */ = {
572 | isa = XCConfigurationList;
573 | buildConfigurations = (
574 | 8EC8C3E11DEC8C3E0044FB44 /* Debug */,
575 | 8EC8C3E21DEC8C3E0044FB44 /* Release */,
576 | );
577 | defaultConfigurationIsVisible = 0;
578 | defaultConfigurationName = Release;
579 | };
580 | /* End XCConfigurationList section */
581 | };
582 | rootObject = 8EC8C3C01DEC8C3E0044FB44 /* Project object */;
583 | }
584 |
--------------------------------------------------------------------------------
/CreditCardForm/Classes/CreditCardFormView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CreditCardForumView.swift
3 | // CreditCardForm
4 | //
5 | // Created by Atakishiyev Orazdurdy on 11/28/16.
6 | // Copyright © 2016 Veriloft. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public enum Brands : String {
12 | case NONE, Visa, UnionPay, MasterCard, Amex, JCB, DEFAULT, Discover
13 | }
14 |
15 | @IBDesignable
16 | public class CreditCardFormView : UIView {
17 |
18 | fileprivate var cardView: UIView = UIView(frame: .zero)
19 | fileprivate var backView: UIView = UIView(frame: .zero)
20 | fileprivate var frontView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 200))
21 | fileprivate var gradientLayer = CAGradientLayer()
22 | fileprivate var showingBack:Bool = false
23 |
24 | fileprivate var backImage: UIImageView = UIImageView(frame: .zero)
25 | fileprivate var brandImageView = UIImageView(frame: .zero)
26 | fileprivate var cardNumber:AKMaskField = AKMaskField(frame: .zero)
27 | fileprivate var cardHolderText:UILabel = UILabel(frame: .zero)
28 | fileprivate var cardHolder:UILabel = UILabel(frame: .zero)
29 | fileprivate var expireDate: AKMaskField = AKMaskField(frame: .zero)
30 | fileprivate var expireDateText: UILabel = UILabel(frame: .zero)
31 | fileprivate var backLine: UIView = UIView(frame: .zero)
32 | fileprivate var cvc: AKMaskField = AKMaskField(frame: .zero)
33 | fileprivate var chipImg: UIImageView = UIImageView(frame: .zero)
34 | fileprivate var cvcAmexImageView: UIImageView = UIImageView(frame: .zero)
35 | fileprivate var amexCVC: AKMaskField = AKMaskField(frame: .zero)
36 | fileprivate var colors = [Brands.DEFAULT.rawValue: [
37 | UIColor.hexStr(hexStr: "363434", alpha: 1),
38 | UIColor.hexStr(hexStr: "363434", alpha: 1)]
39 | ]
40 |
41 | fileprivate var cardNumberCenterXConstraint = NSLayoutConstraint()
42 | fileprivate var amex = false {
43 | didSet {
44 | self.cardNumberCenterXConstraint.constant = (self.amex) ? -20 : 0.0
45 | self.cvcAmexImageView.isHidden = !self.amex
46 | self.amexCVC.isHidden = !self.amex
47 | UIView.animate(withDuration: 0.5) {
48 | self.cardView.layoutIfNeeded()
49 | }
50 | }
51 | }
52 |
53 | public var cardGradientColors = [String : [UIColor]]()
54 |
55 | @IBInspectable
56 | public var defaultCardColor: UIColor = UIColor.hexStr(hexStr: "363434", alpha: 1) {
57 | didSet {
58 | gradientLayer.colors = [defaultCardColor.cgColor, defaultCardColor.cgColor]
59 | backView.backgroundColor = defaultCardColor
60 | }
61 | }
62 |
63 | @IBInspectable
64 | public var cardHolderExpireDateTextColor: UIColor = UIColor.hexStr(hexStr: "#bdc3c7", alpha: 1) {
65 | didSet {
66 | cardHolderText.textColor = cardHolderExpireDateTextColor
67 | expireDateText.textColor = cardHolderExpireDateTextColor
68 | amexCVC.textColor = cardHolderExpireDateColor
69 | }
70 | }
71 |
72 | @IBInspectable
73 | public var cardHolderExpireDateColor: UIColor = .white {
74 | didSet {
75 | cardHolder.textColor = cardHolderExpireDateColor
76 | expireDate.textColor = cardHolderExpireDateColor
77 | cardNumber.textColor = cardHolderExpireDateColor
78 | }
79 | }
80 |
81 | @IBInspectable
82 | public var backLineColor: UIColor = .black {
83 | didSet {
84 | backLine.backgroundColor = backLineColor
85 | }
86 | }
87 |
88 | @IBInspectable
89 | public var chipImage = UIImage(named: "chip", in: Bundle.currentBundle(), compatibleWith: nil) {
90 | didSet {
91 | chipImg.image = chipImage
92 | }
93 | }
94 |
95 | @IBInspectable
96 | public var cvcAmexImageName = UIImage(named: "amexCvc", in: Bundle.currentBundle(), compatibleWith: nil) {
97 | didSet {
98 | cvcAmexImageView.image = cvcAmexImageName
99 | }
100 | }
101 |
102 | @IBInspectable
103 | public var cardHolderString = "----" {
104 | didSet {
105 | cardHolder.text = cardHolderString
106 | }
107 | }
108 |
109 | @IBInspectable
110 | public var cardHolderPlaceholderString = "CARD HOLDER" {
111 | didSet {
112 | cardHolderText.text = cardHolderPlaceholderString
113 | }
114 | }
115 |
116 | @IBInspectable
117 | public var expireDatePlaceholderText = "EXPIRY" {
118 | didSet {
119 | expireDateText.text = expireDatePlaceholderText
120 | }
121 | }
122 |
123 | @IBInspectable
124 | public var cardNumberMaskExpression = "{....} {....} {....} {....}" {
125 | didSet {
126 | cardNumber.maskExpression = cardNumberMaskExpression
127 | }
128 | }
129 |
130 | @IBInspectable
131 | public var cardNumberMaskTemplate = "**** **** **** ****" {
132 | didSet {
133 | cardNumber.maskTemplate = cardNumberMaskTemplate
134 | }
135 | }
136 |
137 | public var cardNumberFont: UIFont = UIFont(name: "HelveticaNeue", size: 20)!
138 | public var cardPlaceholdersFont: UIFont = UIFont(name: "HelveticaNeue", size: 10)!
139 | public var cardTextFont: UIFont = UIFont(name: "HelveticaNeue", size: 12)!
140 |
141 | public override init(frame: CGRect) {
142 | super.init(frame: frame)
143 | createViews()
144 | }
145 |
146 | required public init?(coder aDecoder: NSCoder) {
147 | super.init(coder: aDecoder)
148 | }
149 |
150 | public override func layoutSubviews() {
151 | super.layoutSubviews()
152 | createViews()
153 | }
154 |
155 | private func createViews() {
156 | frontView.isHidden = false
157 | backView.isHidden = true
158 | cardView.clipsToBounds = true
159 |
160 | if colors.count < 7 {
161 | setBrandColors()
162 | }
163 |
164 | createCardView()
165 | createFrontView()
166 | createbackImage()
167 | createBrandImageView()
168 | createCardNumber()
169 | createCardHolder()
170 | createCardHolderText()
171 | createExpireDate()
172 | createExpireDateText()
173 | createChipImage()
174 | createAmexCVC()
175 | createBackView()
176 | createBackLine()
177 | createCVC()
178 | }
179 |
180 | private func setGradientBackground(v: UIView, top: CGColor, bottom: CGColor) {
181 | let colorTop = top
182 | let colorBottom = bottom
183 | gradientLayer.colors = [ colorTop, colorBottom]
184 | gradientLayer.locations = [ 0.0, 1.0]
185 | gradientLayer.frame = v.bounds
186 | backView.backgroundColor = defaultCardColor
187 | v.layer.addSublayer(gradientLayer)
188 | }
189 |
190 | private func createCardView() {
191 | cardView.translatesAutoresizingMaskIntoConstraints = false
192 | cardView.layer.cornerRadius = 6
193 | cardView.backgroundColor = .clear
194 | self.addSubview(cardView)
195 | //CardView
196 | self.addConstraint(NSLayoutConstraint(item: cardView, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: 0.0));
197 |
198 | self.addConstraint(NSLayoutConstraint(item: cardView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1.0, constant: 0.0));
199 |
200 | self.addConstraint(NSLayoutConstraint(item: cardView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1.0, constant: 0.0));
201 |
202 | self.addConstraint(NSLayoutConstraint(item: cardView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.height, multiplier: 1.0, constant: 0.0));
203 | }
204 |
205 | private func createBackView() {
206 | backView.translatesAutoresizingMaskIntoConstraints = false
207 | backView.layer.cornerRadius = 6
208 | backView.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
209 | backView.autoresizingMask = [UIView.AutoresizingMask.flexibleLeftMargin, UIView.AutoresizingMask.flexibleRightMargin, UIView.AutoresizingMask.flexibleTopMargin, UIView.AutoresizingMask.flexibleBottomMargin]
210 | cardView.addSubview(backView)
211 |
212 | self.addConstraint(NSLayoutConstraint(item: backView, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: 0.0));
213 |
214 | self.addConstraint(NSLayoutConstraint(item: backView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1.0, constant: 0.0));
215 |
216 | self.addConstraint(NSLayoutConstraint(item: backView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1.0, constant: 0.0));
217 |
218 | self.addConstraint(NSLayoutConstraint(item: backView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.height, multiplier: 1.0, constant: 0.0));
219 | }
220 |
221 | private func createFrontView() {
222 | frontView.translatesAutoresizingMaskIntoConstraints = false
223 | frontView.layer.cornerRadius = 6
224 | frontView.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
225 | frontView.autoresizingMask = [UIView.AutoresizingMask.flexibleLeftMargin, UIView.AutoresizingMask.flexibleRightMargin, UIView.AutoresizingMask.flexibleTopMargin, UIView.AutoresizingMask.flexibleBottomMargin]
226 | cardView.addSubview(frontView)
227 | setGradientBackground(v: frontView, top: defaultCardColor.cgColor, bottom: defaultCardColor.cgColor)
228 |
229 | self.addConstraint(NSLayoutConstraint(item: frontView, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: 0.0));
230 |
231 | self.addConstraint(NSLayoutConstraint(item: frontView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1.0, constant: 0.0));
232 |
233 | self.addConstraint(NSLayoutConstraint(item: frontView, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1.0, constant: 0.0));
234 |
235 | self.addConstraint(NSLayoutConstraint(item: frontView, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self, attribute: NSLayoutConstraint.Attribute.height, multiplier: 1.0, constant: 0.0));
236 | }
237 |
238 | private func createbackImage() {
239 | backImage.translatesAutoresizingMaskIntoConstraints = false
240 | backImage.image = UIImage(named: "back.jpg")
241 | backImage.contentMode = UIView.ContentMode.scaleAspectFill
242 | frontView.addSubview(backImage)
243 |
244 | self.addConstraint(NSLayoutConstraint(item: backImage, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: 0.0));
245 |
246 | self.addConstraint(NSLayoutConstraint(item: backImage, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1.0, constant: 0.0));
247 |
248 | self.addConstraint(NSLayoutConstraint(item: backImage, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1.0, constant: 0.0));
249 |
250 | self.addConstraint(NSLayoutConstraint(item: backImage, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1.0, constant: 0.0));
251 | }
252 |
253 | private func createBrandImageView() {
254 | //Card brand image
255 | brandImageView.translatesAutoresizingMaskIntoConstraints = false
256 | brandImageView.contentMode = UIView.ContentMode.scaleAspectFit
257 | frontView.addSubview(brandImageView)
258 |
259 | self.addConstraint(NSLayoutConstraint(item: brandImageView, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: 10));
260 |
261 | self.addConstraint(NSLayoutConstraint(item: brandImageView, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1.0, constant: -10));
262 |
263 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[view(==60)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": brandImageView]));
264 |
265 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[view(==40)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": brandImageView]));
266 | }
267 |
268 | private func createCardNumber() {
269 | //Credit card number
270 | cardNumber.translatesAutoresizingMaskIntoConstraints = false
271 | cardNumber.maskExpression = cardNumberMaskExpression
272 | cardNumber.maskTemplate = cardNumberMaskTemplate
273 | cardNumber.textColor = cardHolderExpireDateColor
274 | cardNumber.isUserInteractionEnabled = false
275 | cardNumber.textAlignment = NSTextAlignment.center
276 | cardNumber.font = cardNumberFont
277 | frontView.addSubview(cardNumber)
278 |
279 | cardNumberCenterXConstraint = NSLayoutConstraint(item: cardNumber, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1.0, constant: 0)
280 | self.addConstraint(cardNumberCenterXConstraint);
281 |
282 | self.addConstraint(NSLayoutConstraint(item: cardNumber, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1.0, constant: 0.0));
283 |
284 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[view(==200)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": cardNumber]));
285 |
286 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[view(==30)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": cardNumber]));
287 | }
288 |
289 | private func createCardHolder() {
290 | //Name
291 | cardHolder.translatesAutoresizingMaskIntoConstraints = false
292 | cardHolder.font = cardTextFont
293 | cardHolder.textColor = cardHolderExpireDateColor
294 | cardHolder.text = cardHolderString
295 | frontView.addSubview(cardHolder)
296 |
297 | self.addConstraint(NSLayoutConstraint(item: cardHolder, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1.0, constant: -20));
298 |
299 | self.addConstraint(NSLayoutConstraint(item: cardHolder, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1.0, constant: 15));
300 |
301 | self.addConstraint(NSLayoutConstraint(item: cardHolder, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.height, multiplier: 1.0, constant: 20));
302 | }
303 |
304 | private func createCardHolderText() {
305 | //Card holder uilabel
306 | cardHolderText.translatesAutoresizingMaskIntoConstraints = false
307 | cardHolderText.font = cardPlaceholdersFont
308 | cardHolderText.text = cardHolderPlaceholderString
309 | cardHolderText.textColor = cardHolderExpireDateTextColor
310 | frontView.addSubview(cardHolderText)
311 |
312 | self.addConstraint(NSLayoutConstraint(item: cardHolderText, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardHolder, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: -3));
313 |
314 | self.addConstraint(NSLayoutConstraint(item: cardHolderText, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1.0, constant: 15));
315 | }
316 |
317 | private func createExpireDate() {
318 | //Expire Date
319 | expireDate = AKMaskField()
320 | expireDate.translatesAutoresizingMaskIntoConstraints = false
321 | expireDate.font = cardTextFont
322 | expireDate.maskExpression = "{..}/{..}"
323 | expireDate.text = "MM/YY"
324 | expireDate.textColor = cardHolderExpireDateColor
325 | frontView.addSubview(expireDate)
326 |
327 | self.addConstraint(NSLayoutConstraint(item: expireDate, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1.0, constant: -20));
328 |
329 | self.addConstraint(NSLayoutConstraint(item: expireDate, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1.0, constant: -55));
330 | }
331 |
332 | private func createExpireDateText() {
333 | //Expire Date Text
334 | expireDateText.translatesAutoresizingMaskIntoConstraints = false
335 | expireDateText.font = cardPlaceholdersFont
336 | expireDateText.text = expireDatePlaceholderText
337 | expireDateText.textColor = cardHolderExpireDateTextColor
338 | frontView.addSubview(expireDateText)
339 |
340 | self.addConstraint(NSLayoutConstraint(item: expireDateText, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: expireDate, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: -3));
341 |
342 | self.addConstraint(NSLayoutConstraint(item: expireDateText, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1.0, constant: -58));
343 | }
344 |
345 | private func createAmexCVC() {
346 |
347 | //Create Amex card cvc
348 | amexCVC = AKMaskField()
349 | amexCVC.translatesAutoresizingMaskIntoConstraints = false
350 | amexCVC.font = cardTextFont
351 | amexCVC.text = expireDatePlaceholderText
352 | amexCVC.maskExpression = "{....}"
353 | amexCVC.text = "***"
354 | amexCVC.isHidden = true
355 | frontView.addSubview(amexCVC)
356 |
357 | self.addConstraint(NSLayoutConstraint(item: amexCVC, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1.0, constant: -23));
358 |
359 | self.addConstraint(NSLayoutConstraint(item: amexCVC, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardNumber, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1.0, constant: 15));
360 |
361 | self.addConstraint(NSLayoutConstraint(item: amexCVC, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.width, multiplier: 1.0, constant: 27));
362 |
363 | // Create amex cvc image
364 | cvcAmexImageView.translatesAutoresizingMaskIntoConstraints = false
365 | cvcAmexImageView.image = cvcAmexImageName
366 | cvcAmexImageView.contentMode = ContentMode.scaleAspectFit
367 | cvcAmexImageView.isHidden = true
368 | frontView.addSubview(cvcAmexImageView)
369 |
370 | self.addConstraint(NSLayoutConstraint(item: cvcAmexImageView, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: amexCVC, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1.0, constant: -5));
371 |
372 | self.addConstraint(NSLayoutConstraint(item: cvcAmexImageView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: amexCVC, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1.0, constant: 0));
373 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[view(==15)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": cvcAmexImageView]));
374 |
375 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[view(==15)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": cvcAmexImageView]));
376 |
377 | }
378 |
379 | private func createChipImage() {
380 | //Chip image
381 | chipImg.translatesAutoresizingMaskIntoConstraints = false
382 | chipImg.alpha = 0.5
383 | chipImg.image = chipImage
384 | frontView.addSubview(chipImg)
385 |
386 | self.addConstraint(NSLayoutConstraint(item: chipImg, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: 15));
387 |
388 | self.addConstraint(NSLayoutConstraint(item: chipImg, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: cardView, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1.0, constant: 15));
389 |
390 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[view(==45)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": chipImg]));
391 |
392 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[view(==30)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": chipImg]));
393 | }
394 |
395 | private func createBackLine() {
396 | //BackLine
397 | backLine.translatesAutoresizingMaskIntoConstraints = false
398 | backLine.backgroundColor = backLineColor
399 | backView.addSubview(backLine)
400 |
401 | self.addConstraint(NSLayoutConstraint(item: backLine, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: backView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1.0, constant: 20));
402 |
403 | self.addConstraint(NSLayoutConstraint(item: backLine, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: backView, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1.0, constant: 0));
404 |
405 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[view(==300)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": backLine]));
406 |
407 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[view(==50)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": backLine]));
408 | }
409 |
410 | private func createCVC() {
411 | //CVC textfield
412 | cvc.translatesAutoresizingMaskIntoConstraints = false
413 | cvc.maskExpression = "..."
414 | cvc.text = "CVC"
415 | cvc.backgroundColor = .white
416 | cvc.textAlignment = NSTextAlignment.center
417 | cvc.isUserInteractionEnabled = false
418 | if #available(iOS 13.0, *) {
419 | cvc.backgroundColor = UIColor.systemGray3
420 | }
421 | backView.addSubview(cvc)
422 |
423 | self.addConstraint(NSLayoutConstraint(item: cvc, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: backLine, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1.0, constant: 10));
424 |
425 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[view(==50)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": cvc]));
426 |
427 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[view(==25)]", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["view": cvc]));
428 |
429 | self.addConstraint(NSLayoutConstraint(item: cvc, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: backView, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1.0, constant: -10));
430 | }
431 |
432 | private func setType(colors: [UIColor], alpha: CGFloat, back: UIColor) {
433 | UIView.animate(withDuration: 2, animations: { () -> Void in
434 | self.gradientLayer.colors = [colors[0].cgColor, colors[1].cgColor]
435 | })
436 | self.backView.backgroundColor = back
437 | self.chipImg.alpha = alpha
438 | }
439 |
440 | private func flip() {
441 | var showingSide = frontView
442 | var hiddenSide = backView
443 | if showingBack {
444 | (showingSide, hiddenSide) = (backView, frontView)
445 | }
446 |
447 | UIView.transition(from:showingSide,
448 | to: hiddenSide,
449 | duration: 0.7,
450 | options: [UIView.AnimationOptions.transitionFlipFromRight, UIView.AnimationOptions.showHideTransitionViews],
451 | completion: nil)
452 | }
453 |
454 | public func isAmex() -> Bool {
455 | return self.amex
456 | }
457 |
458 | public func paymentCardTextFieldDidChange(cardNumber: String? = "", expirationYear: UInt?, expirationMonth: UInt?, cvc: String? = "") {
459 | self.cardNumber.text = cardNumber
460 |
461 | if let expireMonth = expirationMonth, let expireYear = expirationYear {
462 | self.expireDate.text = NSString(format: "%02ld", expireMonth) as String + "/" + (NSString(format: "%02ld", expireYear) as String)
463 | }
464 |
465 | if expirationMonth == 0 {
466 | expireDate.text = "MM/YY"
467 | }
468 |
469 | let v = CreditCardValidator()
470 | self.cvc.text = cvc
471 | self.amexCVC.text = cvc
472 |
473 | guard let cardN = cardNumber else {
474 | return
475 | }
476 |
477 | if (cardN.count == 0)
478 | {
479 | self.cardNumber.maskExpression = "{....} {....} {....} {....}"
480 | }
481 | if (cardN.count >= 7 || cardN.count < 4) {
482 | amex = false
483 | guard let type = v.type(from: "\(cardN as String?)") else {
484 | self.brandImageView.image = nil
485 | if let name = colors["NONE"] {
486 | setType(colors: [name[0], name[1]], alpha: 0.5, back: name[0])
487 | }
488 | return
489 | }
490 |
491 | // Visa, Mastercard, Amex etc.
492 | if let name = colors[type.name] {
493 | if(type.name.lowercased() == "amex".lowercased()){
494 | if !amex {
495 | self.cardNumber.maskExpression = "{....} {....} {....} {...}"
496 | self.cardNumber.text = cardNumber
497 | amex = true
498 | }
499 | }
500 | self.brandImageView.image = UIImage(named: type.name, in: Bundle.currentBundle(), compatibleWith: nil)
501 | setType(colors: [name[0], name[1]], alpha: 1, back: name[0])
502 | } else {
503 | setType(colors: [self.colors["DEFAULT"]![0], self.colors["DEFAULT"]![0]], alpha: 1, back: self.colors["DEFAULT"]![0])
504 | }
505 | }
506 | }
507 |
508 | public func paymentCardTextFieldDidEndEditingExpiration(expirationYear: UInt) {
509 | if "\(expirationYear)".count <= 1 {
510 | expireDate.text = "MM/YY"
511 | }
512 | }
513 |
514 | public func paymentCardTextFieldDidBeginEditingCVC() {
515 | if !showingBack {
516 | if !amex {
517 | flip()
518 | showingBack = true
519 | }
520 | }
521 | }
522 |
523 | public func paymentCardTextFieldDidEndEditingCVC() {
524 | if showingBack {
525 | flip()
526 | showingBack = false
527 | }
528 | }
529 |
530 | }
531 |
532 | //: CardColors
533 | extension CreditCardFormView {
534 |
535 | fileprivate func setBrandColors() {
536 | colors[Brands.NONE.rawValue] = [defaultCardColor, defaultCardColor]
537 | colors[Brands.Visa.rawValue] = [UIColor.hexStr(hexStr: "#5D8BF2", alpha: 1), UIColor.hexStr(hexStr: "#3545AE", alpha: 1)]
538 | colors[Brands.MasterCard.rawValue] = [UIColor.hexStr(hexStr: "#ED495A", alpha: 1), UIColor.hexStr(hexStr: "#8B1A2B", alpha: 1)]
539 | colors[Brands.UnionPay.rawValue] = [UIColor.hexStr(hexStr: "#987c00", alpha: 1), UIColor.hexStr(hexStr: "#826a01", alpha: 1)]
540 | colors[Brands.Amex.rawValue] = [UIColor.hexStr(hexStr: "#005B9D", alpha: 1), UIColor.hexStr(hexStr: "#132972", alpha: 1)]
541 | colors[Brands.JCB.rawValue] = [UIColor.hexStr(hexStr: "#265797", alpha: 1), UIColor.hexStr(hexStr: "#3d6eaa", alpha: 1)]
542 | colors["Diners Club"] = [UIColor.hexStr(hexStr: "#5b99d8", alpha: 1), UIColor.hexStr(hexStr: "#4186CD", alpha: 1)]
543 | colors[Brands.Discover.rawValue] = [UIColor.hexStr(hexStr: "#e8a258", alpha: 1), UIColor.hexStr(hexStr: "#D97B16", alpha: 1)]
544 | colors[Brands.DEFAULT.rawValue] = [UIColor.hexStr(hexStr: "#5D8BF2", alpha: 1), UIColor.hexStr(hexStr: "#3545AE", alpha: 1)]
545 |
546 | if cardGradientColors.count > 0 {
547 | for (_, value) in cardGradientColors.enumerated() {
548 | colors[value.key] = value.value
549 | }
550 | }
551 | }
552 | }
553 |
554 |
555 |
--------------------------------------------------------------------------------