prolificinteractive / Caishen

A Payment Card UI & Validator for iOS
MIT License
766 stars 119 forks source link

How to show card image and cvv in Using the different components of the text field separately #115

Closed harshilkotecha closed 6 years ago

harshilkotecha commented 7 years ago

when i follow Using the different components of the text field separately how to show card type image and cvv image in text field ?

harshilkotecha commented 7 years ago

ANSWER 👍 Step 1 : Add image view , Text field 4 ( enter card number , CVV, MM ,YY) Step 2 : Number Text field class - > NumberInputTextField CVV text field class -> CVCInputTextField Month text field class -> MonthInputTextField Year text field class -> YearInputTextField Step 3 : Create @IBOutlet all text field and image view Step 4 : Code here

//
//  ViewController.swift
//  CardDemo
//
//  Created by HarshilKotecha on 11/08/17.
//  Copyright © 2017 HarshilKotecha. All rights reserved.
//

import UIKit
import Caishen
class ViewController: UIViewController, NumberInputTextFieldDelegate, CardInfoTextFieldDelegate    {

    @IBOutlet weak var cardNumberTextField: NumberInputTextField!
    @IBOutlet weak var monthInputTextField: MonthInputTextField!
    @IBOutlet weak var yearInputTextField: YearInputTextField!
    @IBOutlet weak var cvcInputTextField: CVCInputTextField!
    @IBOutlet open weak var cardImageView: UIImageView?

    var card: Card? {
        let number = cardNumberTextField.cardNumber
        let cvc = CVC(rawValue: cvcInputTextField.text ?? "")
        let expiry = Expiry(month: monthInputTextField.text ?? "", year: yearInputTextField.text ?? "")
            ?? Expiry.invalid
        let cardType = cardNumberTextField.cardTypeRegister.cardType(for: cardNumberTextField.cardNumber)

       // let cardType = cardNumberTextField.cardTypeRegister.cardTypeFor(number: cardNumberTextField.cardNumber)
        if cardType.validate(cvc: cvc).union(cardType.validate(expiry: expiry)).union(cardType.validate(number: number)) == .Valid {
            return Card(number: number, cvc: cvc, expiry: expiry)
        } else {
            return nil
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        cardNumberTextField.numberInputTextFieldDelegate = self
        monthInputTextField.cardInfoTextFieldDelegate = self
        yearInputTextField.cardInfoTextFieldDelegate = self
        cvcInputTextField.cardInfoTextFieldDelegate = self

        // Set the `deleteBackwardCallbacks` - closures which are called whenever a user hits
        // backspace on an empty text field.
        monthInputTextField.deleteBackwardCallback = { _ in self.cardNumberTextField.becomeFirstResponder() }
        yearInputTextField.deleteBackwardCallback = { _ in self.monthInputTextField.becomeFirstResponder() }
        cvcInputTextField.deleteBackwardCallback = { _ in self.yearInputTextField.becomeFirstResponder() }

        cardImageView?.image = cardTypeImageStore.image(for: UnknownCardType())
        cardImageView?.layer.cornerRadius = 5.0
        cardImageView?.layer.shadowColor = UIColor.black.cgColor
        cardImageView?.layer.shadowRadius = 2
        cardImageView?.layer.shadowOffset = CGSize(width: 0, height: 0)
        cardImageView?.layer.shadowOpacity = 0.2
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func numberInputTextFieldDidComplete(_ numberInputTextField: NumberInputTextField) {
        cvcInputTextField.cardType = numberInputTextField.cardTypeRegister.cardType(for: numberInputTextField.cardNumber)
        print("Card number: \(numberInputTextField.cardNumber)")
        print(card ?? "")
        monthInputTextField.becomeFirstResponder()
    }

    func numberInputTextFieldDidChangeText(_ numberInputTextField: NumberInputTextField) {
        showCardImage()
    }
    open var cardTypeRegister: CardTypeRegister = CardTypeRegister.sharedCardTypeRegister {
        didSet {
            cardNumberTextField.cardTypeRegister = cardTypeRegister
        }
    }
    open var cardTypeImageStore: CardTypeImageStore = Bundle(for: CardTextField.self)
    internal func showCardImage() {
        let cardType = cardTypeRegister.cardType(for: cardNumberTextField.cardNumber)
        let cardTypeImage = cardTypeImageStore.image(for: cardType)

        cardImageView?.image = cardTypeImage
    }
    func textField(_ textField: UITextField, didEnterValidInfo: String) {
        switch textField {
        case is MonthInputTextField:
            print("Month: \(didEnterValidInfo)")
            yearInputTextField.becomeFirstResponder()
        case is YearInputTextField:
            print("Year: \(didEnterValidInfo)")
            cvcInputTextField.becomeFirstResponder()
        case is CVCInputTextField:
            print("CVC: \(didEnterValidInfo)")
        default:
            break
        }
        print(card ?? "")
    }

    func textField(_ textField: UITextField, didEnterPartiallyValidInfo: String) {
        // The user entered information that is not valid but might become valid on further input.
        // Example: Entering "1" for the CVC is partially valid, while entering "a" is not.
    }

    func textField(_ textField: UITextField, didEnterOverflowInfo overFlowDigits: String) {
        // This function is used in a CardTextField to carry digits to the next text field.
        // Example: A user entered "02/20" as expiry and now tries to append "5" to the month.
        //          On a card text field, the year will be replaced with "5" - the overflow digit.
    }

}
DannyVancura commented 6 years ago

Thanks for posting your solution here! 🙂 Daniel