如何配置文本字段以说明有效期?

时间:2016-06-21 04:18:01

标签: ios swift textfield

我正在输入信用卡信息,我希望有效期限最多为5个字符4个数字,并且在前两个字符后自动输入“/”,即在键入01后自动输入的01/17,并且只允许两个字符“17”。

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
if textField == expire{

    }
    return true
}

5 个答案:

答案 0 :(得分:6)

Swift 4解决方案,基于@Jigar的回答:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if range.length > 0 {
      return true
    }
    if string == "" {
      return false
    }
    if range.location > 4 {
      return false
    }
    var originalText = textField.text
    let replacementText = string.replacingOccurrences(of: " ", with: "")

    //Verify entered text is a numeric value
    if !CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: replacementText)) {
      return false
    }

    //Put / after 2 digit
    if range.location == 2 {
      originalText?.append("/")
      textField.text = originalText
    }
    return true
  }

答案 1 :(得分:4)

尝试这样,它在我的最后工作。

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
    //Range.Lenth will greater than 0 if user is deleting text - Allow it to replce
    if range.length > 0
    {
        if range.location == 3 {
           var originalText = textField.text
           originalText = originalText?.replacingOccurrences(of: "/", with: "")
           textField.text = originalText
        }
        return true
    }

    //Dont allow empty strings
    if string == " "
    {
        return false
    }

    //Check for max length including the spacers we added
    if range.location >= 5
    {
        return false
    }

    var originalText = textField.text
    let replacementText = string.stringByReplacingOccurrencesOfString(" ", withString: "")

    //Verify entered text is a numeric value
    let digits = NSCharacterSet.decimalDigitCharacterSet()
    for char in replacementText.unicodeScalars
    {
        if !digits.longCharacterIsMember(char.value)
        {
            return false
        }
    }

    //Put / space after 2 digit
    if range.location == 2
    {
        originalText?.appendContentsOf("/")
        textField.text = originalText
    }

    return true
}

希望这对你有所帮助。

答案 2 :(得分:1)

答案并不能很好地处理退格。这是我的解决方案(不幸的是在Objective-C中实现):

@interface CreditCardViewController()
<UITextFieldDelegate>
@property (weak,nonatomic) IBOutlet UITextField * cardExpirationTextField;
@property (strong,nonatomic) NSString * previousExpiryDate;
@property (strong,nonatomic) UITextRange * previousExpiryDateSelection;
@property (assign,readonly,nonatomic) NSString * minYearLast2Digits;
@end

@implementation CreditCardViewController

-(instancetype) init
{
    self = [super initWithNibName:NSStringFromClass([CreditCardViewController class]) bundle:nil];
    if(self){
        _minYearLast2Digits = [[[NSNumber numberWithInteger:[NSDate date].year] stringValue] substringFromIndex:2];
    }
    return self;
}

-(void) viewDidLoad
{
    [super viewDidLoad];
    [self setupView]
}

-(void) setupView
{
    self.cardExpirationTextField.delegate = self;
    [self.cardExpirationTextField addTarget:self
                                 action:@selector(reformatCardExpiryDate:)
                       forControlEvents:UIControlEventEditingChanged];
}

-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{

    NSUInteger newLength = [textField.text length] + [string length] - range.length;

    if(textField == self.cardExpirationTextField){
        self.previousExpiryDate = textField.text;
        self.previousExpiryDateSelection = textField.selectedTextRange;
        return newLength <= 5;
    }
    return YES;
}

-(void) reformatCardExpiryDate:(UITextField*) textField
{
    const BOOL isErasing = self.previousExpiryDate.length > textField.text.length;

    BOOL invalid = [textField.text length] > 5;

    if([textField.text length] > 0){
        unichar firstChar = [textField.text characterAtIndex:0];
        invalid |= (firstChar > '1');
    }
    if([textField.text length] > 1){
        unichar firstChar = [textField.text characterAtIndex:0];
        unichar secondChar = [textField.text characterAtIndex:1];
        invalid |= (firstChar == '1' && secondChar > '2');
    }
    if([textField.text length] > 2){
        invalid |= [textField.text characterAtIndex:2] != '/';
    }
    if([textField.text length] > 3){
        unichar yearFirstDigit = [textField.text characterAtIndex:3];
        unichar minYearFirstDigit = [self.minYearLast2Digits characterAtIndex:0];
        invalid |= yearFirstDigit < minYearFirstDigit;
    }
    if([textField.text length] > 4){
        NSString* yearLastTwoDigits = [textField.text substringFromIndex:3];
    invalid |= [yearLastTwoDigits compare:_minYearLast2Digits] == NSOrderedAscending;
    }

    if(invalid){
        [textField setText:self.previousExpiryDate];
        textField.selectedTextRange = self.previousExpiryDateSelection;
        return;
    }

    if(!isErasing && textField.text.length == 2){
        textField.text = [textField.text stringByAppendingString:@"/"];
        UITextPosition *targetPosition =
        [textField positionFromPosition:[textField beginningOfDocument]
                                 offset:textField.text.length];

        [textField setSelectedTextRange:
         [textField textRangeFromPosition:targetPosition
                               toPosition:targetPosition]
         ];
    }

}

@end

答案 3 :(得分:0)

试试这段代码:

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
    let num:NSString = textField.text! ;
    if num.length == 1
    {
        textField.text = NSString(format:"%@%@/",num,string) as String
        return false;
    }
    if num.length >= 5 {
        //        allows only two more characters "17".
        return false;
    }
    return true;
}

答案 4 :(得分:-1)

我刚刚对此进行了编码,对我来说很好用。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        var index = range.lowerBound
        let fecha = textField.text!

        if string == "" {
            var array = Array(fecha)
            array.remove(at: index)
            if array.count > 2 {
                if !array.contains("/"){
                    array.insert("/", at: 2)
                }
            }

            textField.text = String(array)
            let cursorPosition = textField.position(from: textField.beginningOfDocument, offset: index)!
            textField.selectedTextRange = textField.textRange(from: cursorPosition, to: cursorPosition)
        }else{
            let expiracion = fecha.replacingOccurrences(of: "/", with: "")
            if fecha != expiracion{
                if index > 1 {
                    index = range.lowerBound - 1
                }
            }

            var array = Array(expiracion)
            if array.count < 4 {
                print("index: \(index) - \(array)")
                let newChar = Character(string)
                array.insert(newChar, at: index)
                print("new array: ", array)
                if array.count > 2 {
                    array.insert("/", at: 2)
                }
                textField.text = String(array)
                index =  index > 1 ? index + 2 : index + 1
                let cursorPosition = textField.position(from: textField.beginningOfDocument, offset: index)!
                textField.selectedTextRange = textField.textRange(from: cursorPosition, to: cursorPosition)
            }
        }
        return false
}