如何在swift 4中将文本字段输入限制为2位小数?

时间:2017-08-01 16:37:36

标签: ios swift

我有一个文本字段,我想将条目限制为最多2位小数。

允许使用12.34之类的数字但不允许12.345

我该怎么做?

8 个答案:

答案 0 :(得分:18)

将控制器设置为文本字段的委托,并检查建议的字符串是否满足您的要求:

override func viewDidLoad() {
    super.viewDidLoad()
    textField.delegate = self
    textField.keyboardType = .decimalPad
}

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let oldText = textField.text, let r = Range(range, in: oldText) else {
        return true
    }

    let newText = oldText.replacingCharacters(in: r, with: string)
    let isNumeric = newText.isEmpty || (Double(newText) != nil)
    let numberOfDots = newText.components(separatedBy: ".").count - 1

    let numberOfDecimalDigits: Int
    if let dotIndex = newText.index(of: ".") {
        numberOfDecimalDigits = newText.distance(from: dotIndex, to: newText.endIndex) - 1
    } else {
        numberOfDecimalDigits = 0
    }

    return isNumeric && numberOfDots <= 1 && numberOfDecimalDigits <= 2
}

答案 1 :(得分:3)

伙计们,这是解决方案:

{{1}}

答案 2 :(得分:3)

在Swift 4中。

TextField有10位数字的限制,十进制2位数字的限制(可以更改Limits)。点在文本字段中仅允许一次。

config.middleware.use "ProxyPassCookie"

答案 3 :(得分:2)

import pyglet
from pyglet.gl import *
from pyglet.window import mouse


class Drainage_Window(pyglet.window.Window):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.set_minimum_size(300, 300)

    def on_draw(self):
        self.clear()


if __name__ == '__main__':
    window = Drainage_Window(width=1920 // 4, height=1080//4,
                             caption="Drainage Network", resizable=True)
    glClearColor(0.7, 0.7, 1, 1)

    @window.event
    def on_mouse_press(x, y, button, modifiers):
        if button == mouse.LEFT:
            print('The left mouse button was pressed.')
            label = pyglet.text.Label('Click!',
                                  font_name='Times New Roman',
                                  font_size=16,
                                  x=x, y=y,
                                  anchor_x='center', anchor_y='center')

            window.push_handlers(pyglet.window.event.WindowEventLogger())

            @window.event
            def on_draw():
                label.draw()

    pyglet.app.run()

答案 4 :(得分:1)

Code Different's answer之后,我改进了代码以在同一类中支持不同的Locale和不同的UITextField。

  func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard textField.keyboardType == .decimalPad, let oldText = textField.text, let r = Range(range, in: oldText) else {
        return true
    }

    let newText = oldText.replacingCharacters(in: r, with: string)
    let isNumeric = newText.isEmpty || (Double(newText) != nil)

    let formatter = NumberFormatter()
    formatter.locale = Locale.current
    let decimalPoint = formatter.decimalSeparator ?? "."
    let numberOfDots = newText.components(separatedBy: decimalPoint).count - 1

    let numberOfDecimalDigits: Int
    if let dotIndex = newText.index(of: ".") {
        numberOfDecimalDigits = newText.distance(from: dotIndex, to: newText.endIndex) - 1
    } else {
        numberOfDecimalDigits = 0
    }
    return isNumeric && numberOfDots <= 1 && numberOfDecimalDigits <= 2
  }

答案 5 :(得分:0)

没有一个答案处理完了decimalSeparator和我遇到的所有极端情况,所以我决定编写自己的答案。

extension YourController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let text = textField.text, let decimalSeparator = NSLocale.current.decimalSeparator else {
            return true
        }

         var splitText = text.components(separatedBy: decimalSeparator)
         let totalDecimalSeparators = splitText.count - 1
         let isEditingEnd = (text.count - 3) < range.lowerBound

         splitText.removeFirst()

         // Check if we will exceed 2 dp
         if
             splitText.last?.count ?? 0 > 1 && string.count != 0 &&
             isEditingEnd
         {
             return false
         }

         // If there is already a dot we don't want to allow further dots
         if totalDecimalSeparators > 0 && string == decimalSeparator {
             return false
         }

         // Only allow numbers and decimal separator
         switch(string) {
         case "", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", decimalSeparator:
             return true
         default:
             return false
         }
     }
 }

答案 6 :(得分:0)

仅允许使用两个小数点,并且仅允许一个“”。允许

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

                    let text: NSString = textField.text! as NSString
                    let resultString = text.replacingCharacters(in: range, with: string)


        //Check the specific textField 
         if textField == costTextField {
             let textArray = resultString.components(separatedBy: ".")
             if textArray.count > 2 { //Allow only one "."
                return false
             }
           if textArray.count == 2 {
              let lastString = textArray.last
             if lastString!.count > 2 { //Check number of decimal places 
                   return false
               }
            }
          }
           return true
       }

答案 7 :(得分:0)

快速5。添加到Enrique的答案(基于不同的Code基准)中,我发现需要允许Delete键在行的任何位置进行操作,并在其开头加上一个符号(+或-)或小数点。输入行。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    // Limit number fields to +/- Real #s: sign as first character, one decimal separator, one decimal place after separator
    if string.isEmpty { return true }   // Allow delete key anywhere!
    guard let oldText = textField.text, let rng = Range(range, in: oldText) else {
        return true
    }
    let newText = oldText.replacingCharacters(in: rng, with: string)

    let isNumeric = newText.isEmpty || (Double(newText) != nil)

    let formatter = NumberFormatter()
    formatter.locale = .current
    let decimalPoint = formatter.decimalSeparator ?? "."
    let numberOfDots = newText.components(separatedBy: decimalPoint).count - 1

    let numberOfDecimalDigits: Int
    if let dotIndex = newText.firstIndex(of: ".") {
        numberOfDecimalDigits = newText.distance(from: dotIndex, to: newText.endIndex) - 1
    } else {
        numberOfDecimalDigits = 0
    }
    if newText.count == 1 && !isNumeric {   // Allow first character to be a sign or decimal point
        return CharacterSet(charactersIn: "+-" + decimalPoint).isSuperset(of: CharacterSet(charactersIn: string))
    }
    return isNumeric && numberOfDots <= 1 && numberOfDecimalDigits <= 1
}