ios xx-xx-xxx 中的 UITextField 格式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7709450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:48:36  来源:igfitidea点击:

UITextField format in xx-xx-xxx

iphoneobjective-ciosuitextfield

提问by PJR

I am using UITextField and i want that should take character in the format of xx-xx-xxx only numbers.

我正在使用 UITextField 并且我希望它只采用 xx-xx-xxx 数字格式的字符。

any help ?

有什么帮助吗?

采纳答案by Narayana

Try below it will work

在下面尝试它会起作用

Objective-C

目标-C

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    int groupingSize = 2;
    if([string length] == 0) {
        groupingSize = 4;
    }
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init] ;
    NSString *separator = @"-";
    [formatter setGroupingSeparator:separator];
    [formatter setGroupingSize:groupingSize];
    [formatter setUsesGroupingSeparator:YES];
    [formatter setSecondaryGroupingSize:2];
    if (![string  isEqual: @""] && (textField.text != nil && textField.text.length > 0)) {
        NSString *num = textField.text;
        num = [num stringByReplacingOccurrencesOfString:separator withString:@""];
        NSString *str = [formatter stringFromNumber:[NSNumber numberWithDouble:[num doubleValue]]];
        textField.text = str;
    }
    return YES;
}

Swift-3

斯威夫特-3

extension ViewController: UITextFieldDelegate {

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        var groupSize = 2
        let separator = "-"
        if string.characters.count == 0 {
            groupSize = 4
        }
        let formatter = NumberFormatter()
        formatter.groupingSeparator = separator
        formatter.groupingSize = groupSize
        formatter.usesGroupingSeparator = true
        formatter.secondaryGroupingSize = 2
        if var number = textField.text, string != "" {
            number = number.replacingOccurrences(of: separator, with: "")
            if let doubleVal = Double(number) {
                let requiredString = formatter.string(from: NSNumber.init(value: doubleVal))
                textField.text = requiredString
            }

        }
        return true
    }
}

回答by BadPirate

Had a need to do this nicely for a phone numbers with a variable format, here's what I wrote. Feel free to reuse - First I've got a method to filter a formatted string, with # being a number, and any other character being some kind of "filler" that should be conveniently inserted after the user gets to the place where it's needed.

需要为具有可变格式的电话号码很好地做到这一点,这就是我写的。随意重用 - 首先,我有一种过滤格式化字符串的方法,其中 # 是一个数字,任何其他字符都是某种“填充符”,应该在用户到达需要的地方后方便地插入.

NSMutableString *filteredPhoneStringFromStringWithFilter(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 ? '
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    NSString *filter = @"(###) ### - ####";

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

    NSString *changedString = [textField.text stringByReplacingCharactersInRange:range withString:string];

    if(range.length == 1 && // Only do for single deletes
       string.length < range.length &&
       [[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 = filteredPhoneStringFromStringWithFilter(changedString, filter);

    return NO;
}
' : [string characterAtIndex:onOriginal]; switch (filterChar) { case '#': if(originalChar=='
override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    self.tfCardNumber.addTarget(self, action: "creditCardNumberFormatter:", forControlEvents: .EditingChanged)
    self.tfExpiryValue.addTarget(self, action: "creditCardExpiryFormatter:", forControlEvents: .EditingChanged)

}// end viewDidAppear

  func creditCardNumberFormatter(sender: AnyObject!) {

    // create object universally access global methods
    var objMethodInc = MethodInc(object: self)

    var formattedText = objMethodInc.formatCreditCard(self.tfCardNumber.text)

    if formattedText != self.tfCardNumber.text {

        self.tfCardNumber.text = formattedText

    }

    if countElements(self.tfCardNumber.text) == 19 {

        self.tfCardNumber.resignFirstResponder()
        self.tfExpiryValue.becomeFirstResponder()

    }


}// end creditCardNumberFormatter

func creditCardExpiryFormatter(sender: AnyObject!) {

    // create object universally access global methods
    var objMethodInc = MethodInc(object: self)

    var formattedText = objMethodInc.formatCreditCardExpiry(self.tfExpiryValue.text)

    if formattedText != self.tfExpiryValue.text {

        self.tfExpiryValue.text = formattedText

    }

}// end creditCardExpiryFormatter
') { // 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] = '
// delegate for textfield

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

    if string == "" {
        return true
    }

    if textField == self.tfCardNumber {

        if countElements(self.tfCardNumber.text) > 18 {

            return false

        } else if textField == self.tfExpiryValue {

            if countElements(self.tfExpiryValue.text) > 4 {
                return false
            }

        }
    }

    return true

}// end textField
'; // Cap the output string return [NSString stringWithUTF8String:outputString]; }

Now so that they can delete through filler, I modified my should change characters in range.

现在,为了他们可以通过填充符删除,我修改了我应该更改范围内的字符。

func formatCreditCard(input: NSString) -> String {

    var input = self.trimSpecialCharacters(input);

    println("formatCreditCard input \(input)")

    var output : NSString?

    switch (input.length) {

    case 1: output = input
    case 2: output = input
    case 3: output = input
    case 4:
        var vs = input.substringToIndex(input.length)
        output = NSString(string: "\(vs)")
        break

    case 5: output = input
    case 6: output = input
    case 7: output = input
    case 8:
        var vs1 = input.substringToIndex(4)
        var vs2 = input.substringFromIndex(4)
        output = NSString(string: "\(vs1)-\(vs2)")
        break

    case 9: output = input
    case 10: output = input
    case 11: output = input

    case 12:
        var vs1 = input.substringToIndex(4)
        var vs2 = input.substringWithRange(NSMakeRange(4, 4))
        var vs3 = input.substringFromIndex(8)
        output = NSString(string: "\(vs1)-\(vs2)-\(vs3)")
        break

    case 13: output = input
    case 14: output = input
    case 15: output = input
    case 16:
        var vs1 = input.substringToIndex(4)
        var vs2 = input.substringWithRange(NSMakeRange(4, 4))
        var vs3 = input.substringWithRange(NSMakeRange(8, 4))
        var vs4 = input.substringFromIndex(12)
        output = NSString(string: "\(vs1)-\(vs2)-\(vs3)-\(vs4)")
        break
    default:
        output = input
        break

    }//  end switch

    println("formatCreditCard out \(output!)")

    return output!

}// end  formatCreditCard


// prgm mark ----

func formatCreditCardExpiry(input: NSString) -> String {

    var output : NSString?

    var input = self.trimSpecialCharacters(input);

    switch (input.length) {

    case 1: output = input
    case 2:
        var vs = input.substringToIndex(input.length)
        output = NSString(string: "\(vs)")
        break

    case 3: output = input
    case 4:
        var vs1 = input.substringToIndex(2)
        var vs2 = input.substringFromIndex(2)
        output = NSString(string: "\(vs1)/\(vs2)")
        break
    default:
        output = input
        break
    }

    return output!

}// end  formatCreditCardExpiry


func trimSpecialCharacters(input: NSString) -> NSString {

    var special = NSCharacterSet(charactersInString: "/+-() ")

    var comp = input.componentsSeparatedByCharactersInSet(special) as NSArray

    return comp.componentsJoinedByString("")

}//end trimSpecialCharacters

This provides a really clean way to force users to enter numbers in a particular format.

这提供了一种非常干净的方式来强制用户以特定格式输入数字。

回答by El Developer

Implement your logic inside textField:shouldChangeCharactersInRange:replacementString:which is a delegate method.

实现您的逻辑,textField:shouldChangeCharactersInRange:replacementString:其中是一个委托方法。

回答by Vinod Joshi

Swift kind of long method but works fine: iOS 8

Swift 一种很长的方法,但效果很好:iOS 8

ViewController // programming mark ----- ----- ---- ----- ----- ---- ----- ----- ----

ViewController // 编程标记 ----- ----- ---- ----- ----- ---- ----- ----- ----

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let separator = "-"
    let filler = "X"
    if var number = textField.text, string != "" {
        number = number.replacingOccurrences(of: separator, with: "")
        number = number.replacingOccurrences(of: filler, with: "")
        if number.count == 10 { return false }
        number += string
        while number.count < 10 { number += "X" }
        number.insert("-", at: number.index(number.startIndex,
                                            offsetBy: 6))
        number.insert("-", at: number.index(number.startIndex,
                                            offsetBy: 3))
        textField.text = number
    }
    return false
}

// prgm mark --- ---- --- ----

// 程序标记 --- ---- --- ----

func textFieldDidBeginEditing(_ textField: UITextField) {
        // When you start editing check if there is nothing, in that case add the entire mask
        if let text = textField.text, text == "" || text == "DD/MM/YYYY" {
            textField.text = "DD/MM/YYYY"
            textField.textColor = .lightGray
            textField.setCursor(position: text.count)
        }
    }

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    guard var number = textField.text else {
        return true
    }
    // If user try to delete, remove the char manually
    if string == "" {
        number.remove(at: number.index(number.startIndex, offsetBy: range.location))
    }
    // Remove all mask characters
    number = number.replacingOccurrences(of: "/", with: "")
    number = number.replacingOccurrences(of: "D", with: "")
    number = number.replacingOccurrences(of: "M", with: "")
    number = number.replacingOccurrences(of: "Y", with: "")

    // Set the position of the cursor
    var cursorPosition = number.count+1
    if string == "" {
        //if it's delete, just take the position given by the delegate
        cursorPosition = range.location
    } else {
        // If not, take into account the slash
        if cursorPosition > 2 && cursorPosition < 5 {
            cursorPosition += 1
        } else if cursorPosition > 4 {
            cursorPosition += 2
        }
    }
    // Stop editing if we have rich the max numbers
    if number.count == 8 { return false }
    // Readd all mask char
    number += string
    while number.count < 8 {
        if number.count < 2 {
            number += "D"
        } else if number.count < 4 {
            number += "M"
        } else {
            number += "Y"
        }
    }
    number.insert("/", at: number.index(number.startIndex, offsetBy: 4))
    number.insert("/", at: number.index(number.startIndex, offsetBy: 2))

    // Some styling
    let enteredTextAttribute = [NSForegroundColorAttributeName: UIColor.black, NSFontAttributeName: UIFont.systemFont(ofSize: 15)]
    let maskTextAttribute = [NSForegroundColorAttributeName: UIColor.lightGray, NSFontAttributeName: UIFont.systemFont(ofSize: 15)]

    let partOne = NSMutableAttributedString(string: String(number.prefix(cursorPosition)), attributes: enteredTextAttribute)
    let partTwo = NSMutableAttributedString(string: String(number.suffix(number.count-cursorPosition)), attributes: maskTextAttribute)

    let combination = NSMutableAttributedString()

    combination.append(partOne)
    combination.append(partTwo)

    textField.attributedText = combination
    textField.setCursor(position: cursorPosition)


    return false
}

func textFieldDidEndEditing(_ textField: UITextField) {
    if let text = textField.text, text != "" && text != "DD/MM/YYYY" {
        // Do something with your value
    } else {
        textField.text = ""
    }
}

----------- INSIDE your command method or file --------

----------- 在您的命令方法或文件中 --------

// prgm mark ----

//程序标记----

extension UITextField {
    func setCursor(position: Int) {
        let position = self.position(from: beginningOfDocument, offset: position)!
        selectedTextRange = textRange(from: position, to: position)
    }
}

回答by Michael Ryan Villanueva

Here is my take on it after looking at everyone's answers.

看了大家的回答,我的看法是这样的。

Swift 4

斯威夫特 4

extension String {
    func applyPatternOnNumbers(pattern: String, replacmentCharacter: Character) -> String {
        var pureNumber = self.replacingOccurrences( of: "[^0-9]", with: "", options: .regularExpression)
        for index in 0 ..< pattern.count {
            guard index < pureNumber.count else { return pureNumber }
            let stringIndex = String.Index(encodedOffset: index)
            let patternCharacter = pattern[stringIndex]
            guard patternCharacter != replacmentCharacter else { continue }
            pureNumber.insert(patternCharacter, at: stringIndex)
        }
        return pureNumber
    }
}

回答by RomOne

My solution works like that:

我的解决方案是这样工作的:

enter image description here

在此处输入图片说明

Implement in your textfield delegates:

在您的文本字段委托中实施:

 guard let text = textField.text else { return }
 textField.text = text.applyPatternOnNumbers(pattern: "##-##-###", replacmentCharacter: "#")

And that little helper as an extension:

还有那个小帮手作为扩展:

extension String {
    func applyPatternOnNumbers(pattern: String, filler: Character) -> String {
        var pureNumber = self.replacingOccurrences( of: "[^0-9]", with: "", options: .regularExpression)
        // Insert filler for all occurances of filler in pattern
        for index in pattern.indices {
            print(pattern[index])
            let patternChar = pattern[index]
            if patternChar == filler {
                if index <= pureNumber.endIndex {
                    pureNumber.insert(filler, at: index)
                }
            }
        }
        return pureNumber
    }
}

PS: there is still a bug in that implementation when you try to move the cursor while editing

PS:当您在编辑时尝试移动光标时,该实现中仍然存在错误

回答by Дар?я Прокопович

You can call path into this method any pattern you need for your textField:

您可以将路径调用到此方法中,您的 textField 所需的任何模式:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if(text == "\n") {
        textView.resignFirstResponder()
        return false
    } else if !text.isEmpty {
        guard let text = textView.text else { return true }
        textView.text = text.applyPatternOnNumbers(pattern: "###-##-####", filler: "-")
    }
    return true
}

Example:

例子:

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

回答by dsunku

This worked for me after a little bit of customization from one of the answers.

从其中一个答案中进行了一些自定义后,这对我有用。

NSDateFormatter *formatter;
NSString        *dateString;

formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"dd-MM-yyyy HH:mm"]; //or something in your own style

dateString = [formatter stringFromDate:[NSDate date]];

[formatter release];  // maybe; you might want to keep the formatter 
                      // if you're doing this a lot.

Usage:

用法:

##代码##

回答by James Webster

My google searches tell me that you should implement

我的谷歌搜索告诉我你应该实施

##代码##

from the UITextFieldDelegateprotocol.

UITextFieldDelegate协议。

Have a look at thisfor more info.

看看这个了解更多信息。

回答by Totumus Maximus

If you want it to be something like a date then you can make your own date formatter like this:

如果您希望它像日期一样,那么您可以像这样制作自己的日期格式化程序:

##代码##

Getting Current Time in string in Custom format in objective c

在目标c中以自定义格式获取字符串中的当前时间