Internship/2020 year-end summer internship

Setting an overlay for textfield (on the left)

hajinny 2021. 2. 12. 11:20

This functionality is actually super easy to implement, if you are familiar with how UITextFieldDelegate works in objective C (an article was written about this 2 articles ago).

 

I had to find a way to do something like this:

This is done like this:

//
//  ViewController.m
//  Tutorial
//
//  Created by Developer on 9/02/21.
//  Copyright © 2021 Developer. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
- (IBAction)hello:(id)sender;
@property (weak, nonatomic) IBOutlet UITextField *creditTextField;

@end

@implementation ViewController

static NSString *const visaRegex = @"^4[0-9]{6,}$";
static NSString *const mastercardRegex = @"^5[1-5][0-9]{5,}|222[1-9][0-9]{3,}|22[3-9][0-9]{4,}|2[3-6][0-9]{5,}|27[01][0-9]{4,}|2720[0-9]{3,}$";
static NSString *const americanexpressRegex = @"^3[47][0-9]{5,}$";

- (IBAction)hello:(id)sender{
    NSLog(@"hi!");
    
    
}
- (void)setTextFieldImage: (UITextField*)textField :(NSString *)iconName
{
    
    
    UIImage *image = [UIImage imageNamed:iconName];
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(24, 24), NO, 1.0);
    [image drawInRect:CGRectMake(0, 0, 24, 24)];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageView *leftImageView = [[UIImageView alloc] initWithImage:image];
    
    leftImageView.contentMode = UIViewContentModeLeft;
    leftImageView.frame = CGRectMake(0.0f, 0.0f, leftImageView.image.size.width + 10.0f, leftImageView.image.size.height);

    textField.leftViewMode = UITextFieldViewModeAlways;
    textField.leftView = leftImageView;
}
- (void)viewDidLoad {
    [self setTextFieldImage:_creditTextField :@"card"];
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.creditTextField.delegate = self;
}

- (BOOL)checkRegex:(NSString *)pattern against:(NSString *)raw{
    return [raw rangeOfString:pattern options:NSRegularExpressionSearch].location != NSNotFound;
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    NSString *filter = @"#### #### #### ####";

    if(!filter) return YES; // No filter provided, allow anything

    NSLog(@"%@", NSStringFromRange(range));
    NSLog(@"%@", string);
    NSString *changedString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    
    if(range.length == 1 && // Only do for single deletes
       [[textField.text substringWithRange:range] rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"0123456789"]].location == NSNotFound)
    {
        // Something was deleted.  Delete past the previous number
        NSInteger location = changedString.length-1;
        if(location >= 0)
        {
            for(; location > 0; location--)
            {
                if(isdigit([changedString characterAtIndex:location]))
                {
                    break;
                }
            }
            changedString = [changedString substringToIndex:location];
        }
    }
    textField.text = filteredCreditCardStringFromStringWithFilter(changedString, filter);
    
    NSString *rawCreditCard = [textField.text stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    if([self checkRegex:visaRegex against:rawCreditCard]){
        [self setTextFieldImage:_creditTextField :@"visa"];
    }else if([self checkRegex:mastercardRegex against:rawCreditCard]){
        [self setTextFieldImage:_creditTextField :@"mastercard"];
    }else if([self checkRegex:americanexpressRegex against:rawCreditCard]){
        [self setTextFieldImage:_creditTextField :@"americanexpress"];
    }else{
        [self setTextFieldImage:_creditTextField :@"card"];
    }
    
    return NO;
}
NSString *filteredCreditCardStringFromStringWithFilter(NSString *string, NSString *filter)
{
    NSUInteger onOriginal = 0, onFilter = 0, onOutput = 0;
    char outputString[([filter length])];
    BOOL done = NO;

    while(onFilter < [filter length] && !done)
    {
        char filterChar = [filter characterAtIndex:onFilter];
        char originalChar = onOriginal >= string.length ? '\0' : [string characterAtIndex:onOriginal];
        switch (filterChar) {
            case '#':
                if(originalChar=='\0')
                {
                    // We have no more input numbers for the filter.  We're done.
                    done = YES;
                    break;
                }
                if(isdigit(originalChar))
                {
                    outputString[onOutput] = originalChar;
                    onOriginal++;
                    onFilter++;
                    onOutput++;
                }
                else
                {
                    onOriginal++;
                }
                break;
            default:
                // Any other character will automatically be inserted for the user as they type (spaces, - etc..) or deleted as they delete if there are more numbers to come.
                outputString[onOutput] = filterChar;
                onOutput++;
                onFilter++;
                if(originalChar == filterChar)
                    onOriginal++;
                break;
        }
    }
    outputString[onOutput] = '\0'; // Cap the output string
    return [NSString stringWithUTF8String:outputString];
}


@end