【问题标题】:UITextField format in xx-xx-xxxUITextField 格式为 xx-xx-xxx
【发布时间】:2011-12-04 07:10:03
【问题描述】:

我正在使用 UITextField,我希望它应该采用 xx-xx-xxx 格式的字符。

有什么帮助吗?

【问题讨论】:

    标签: iphone objective-c ios uitextfield


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      来自UITextFieldDelegate 协议。

      查看this 了解更多信息。

      【讨论】:

        【解决方案3】:

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

        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.
        

        Getting Current Time in string in Custom format in objective c

        【讨论】:

          【解决方案4】:

          试试下面就行了

          Objective-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

          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
              }
          }
          

          【讨论】:

          • 移除 NSNumberFormatter 初始化时的自动释放
          • @Narayana 它正在工作,但如果我的字符串以 0 开头,它将自动删除 0。我应该怎么做才能防止它自动删除0?
          • 您能否添加 swift 版本,因为 swift 需要 2 -3 更改以避免崩溃
          • @AbhishekThapliyal 请检查更新的答案我已经添加了 swift3 代码,如果您遇到任何问题,请告诉我
          • @AbhishekThapliyal 请检查上面更新的答案让分隔符 = “-” 代替 - 使用 \\ 它会按您的需要工作
          【解决方案5】:

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

          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 ? '\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];
          }
          

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

          - (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;
          }
          

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

          【讨论】:

          • 我不知道为什么这没有得到更多的支持。它完全完成了我需要它做的事情,而且完全没有大惊小怪:我复制、粘贴、更改了非常清晰的格式掩码(需要不同的格式),它完美地工作。完美。
          • 使这个想法适用于日期和时间(包括上午/下午)。 1. NSString *filter = @"##/##/#### ##:## ##"; 2. 字符集 - [NSCharacterSet characterSetWithCharactersInString:@"0123456789APMapm"], 3. 将 else 添加到过滤的PhoneStringFromStringWithFilter 类型方法 - else if((originalChar == 'a') || (originalChar == 'p') || (originalChar = = 'm') || (originalChar == 'A') || (originalChar == 'P') || (originalChar == 'M')){ outputString[onOutput] = originalChar; onOriginal++;过滤器++;输出++; }
          • 如何适应这样的过滤器:(##) ####-####。当我尝试这个时,第一个括号永远不会被删除。
          • @AndréCytryn - 那是因为这是为了强制执行格式...如果前几个字符不是可变的(不是 #),那么它们将始终存在(无法删除) - - 虽然您可以修改上述方法以满足您的需要:)
          【解决方案6】:

          Swift 一种长方法,但工作正常:iOS 8

          视图控制器 // 编程标记 ----- ----- ---- ----- ----- ---- ----- ----- ----

          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
          

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

          // 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
          

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

          //程序标记----

          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
          

          【讨论】:

          • 你应该多解释一下你的代码做了什么,这真的很难理解......不要忘记阅读这篇文章的人并没有创建你的代码:对你来说似乎很明显不是给任何阅读它的人。谢谢!
          【解决方案7】:

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

          斯威夫特 4

          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
          }
          

          【讨论】:

          • 这工作正常,但我无法删除数字或将光标放在中间并更改数字
          【解决方案8】:

          我的解决方案是这样的:

          在您的文本字段代表中实现:

          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 = ""
              }
          }
          

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

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

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

          【讨论】:

          • 你完成这个没有错误吗?如果是,请分享演示项目提前致谢
          【解决方案9】:

          你可以在这个方法中调用你文本字段所需的任何模式:

          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(utf16Offset: index, in: pattern)
                      let patternCharacter = pattern[stringIndex]
                      guard patternCharacter != replacmentCharacter else { continue }
                      pureNumber.insert(patternCharacter, at: stringIndex)
                  }
                  return pureNumber
              }
          }
          

          例子:

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

          【讨论】:

          • 如何在文本字段中快速输入 9 位数字,如 XXX-XXXXXX
          【解决方案10】:

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

          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
              }
          }
          

          用法:

          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
          }
          

          【讨论】:

          • 当我尝试从文本字段中删除文本时无法正常工作
          【解决方案11】:

          基于#dsunku 回答,仅提供有效的解决方案:

          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
            }
          }
          

          用法:

          func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
              let text = (textField.text ?? "")
              let str = text.replacingCharacters(in: Range(range, in: text)!, with: string)
              
              let previousTextIntendedToDelete = text.count == 2 && string == ""
              let newTextIntendedToAdd = str.count == 3 && string != ""
          
          if(text == "\n") {
              textField.resignFirstResponder()
              return false
          } else if !text.isEmpty && !previousTextIntendedToDelete && newTextIntendedToAdd {
              textField.text = text.applyPatternOnNumbers(pattern: "###-##-####", filler: "-")
          }
          return true
          

          }

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-04-07
            • 2015-04-06
            • 1970-01-01
            • 1970-01-01
            • 2016-12-24
            • 1970-01-01
            • 1970-01-01
            • 2013-05-22
            相关资源
            最近更新 更多