Swiftでは、テキストフィールドに整数が含まれている場合にのみ、ボタンを有効にするテキストフィールドを作成しようとしています。これどうやってするの?
UITextFieldDelegate
を追加して、View ControllerをUITextFieldDelegate
にします。IBOutlet
sを追加します。viewDidLoad
で、ボタンのisEnabled
プロパティをfalse
に設定し、self
を_textField.delegate
_として設定します。textField:shouldChangeCharactersInRange:replacementString:
_メソッドを実装します。このメソッドは、テキストフィールドが編集されるたびに呼び出されます。そこで、Int(text)
を呼び出して、現在のテキストフィールドがInt
に変換されるかどうかを確認し、必要に応じてボタンを有効/無効にします。コードは次のとおりです。
_class ViewController : UIViewController, UITextFieldDelegate {
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.isEnabled = false
textField.delegate = self
textField.keyboardType = .numberPad
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// Find out what the text field will be after adding the current edit
let text = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
if Int(text) != nil {
// Text field converted to an Int
button.isEnabled = true
} else {
// Text field is not an Int
button.isEnabled = false
}
// Return true so the text field will be changed
return true
}
}
_
2つのこと:
テンキーのみを表示するには、キーボードの種類を指定します。したがって、keyboardType
を.numberPad
に設定します。ただし、これは、ユーザーがテキストフィールドに無効な文字を入力するのを止めるのに十分ではありません。たとえば、iPadを使用している場合でも、ユーザーはテキストを貼り付けたり、キーボードを切り替えたりすることができます。
テキストフィールドのデリゲートを指定し、0
を介して数字9
以外の文字を受け入れないshouldChangeCharactersInRange
を実装します。
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// you can set the following two properties for the text field in Interface Builder, if you'd prefer
textField.delegate = self
textField.keyboardType = .numberPad
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let invalidCharacters = CharacterSet(charactersIn: "0123456789").inverted
return string.rangeOfCharacter(from: invalidCharacters) == nil
}
// or, alternatively:
//
// func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
// return string.range(of: "^\\d*$", options: .regularExpression) != nil
// }
}
Swift 2レンディションについては、この回答の以前のリビジョンを参照してください。
Swift 4:単純なguard
とtypecasting to Int
以下のように
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let _ = Int(string) else {
button.isEnabled = false
return true
}
button.isEnabled = true
return true
}
最初に、独自のクラスでUITextViewDelegateクラスを継承する必要があります
class ViewController: UIViewController, UITextViewDelegate {
2番目にIBOutletを追加します
@IBOutlet weak var firstName: UITextField!
3番目は、このオブジェクトが使用していることを保証する必要があります
override func viewDidLoad() {
super.viewDidLoad()
firstName.delegate = self
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == firstName {
let allowedCharacters = "1234567890"
let allowedCharacterSet = CharacterSet(charactersIn: allowedCharacters)
let typedCharacterSet = CharacterSet(charactersIn: string)
let alphabet = allowedCharacterSet.isSuperset(of: typedCharacterSet)
return alphabet
}
}
各テキストフィールドにはkeyboardType
があります。これを_UIKeyboardType.NumbersAndPunctuation
_に設定して、数字のみを表示し、リターンキーを表示したままにすることができます(防御UI)。次に、NSScanner
のscanInt()
を使用して、textField.textが有効な整数であるかどうかを確認できます。
バックスペースと他の制御文字を受け入れるために、私は次の方法を使用しました:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string.isEmpty { // This is for accept control characters
return true
}
let numericRegEx = "[0-9]"
let predicate = NSPredicate(format:"SELF MATCHES %@", numericRegEx)
let newText = (textFieldCount.text as! NSString).replacingCharacters(in: range, with: string)
return predicate.evaluate(with: string)
}
浮動小数点も受け入れたい場合は、RegExを
let numericRegEx = "[.0-9]"
テキストサイズを10に制限する場合、最後の行を次のように変更します。
return predicate.evaluate(with: string) && newText.count < 10
NSScannerを使用してこれを行うことができますこれはこれを使用して試してみると便利かもしれません
if( [[NSScanner scannerWithString:@"-123.4e5"] scanFloat:NULL] )
NSLog( @"\"-123.4e5\" is numeric" );
else
NSLog( @"\"-123.4e5\" is not numeric" );
if( [[NSScanner scannerWithString:@"Not a number"] scanFloat:NULL] )
NSLog( @"\"Not a number\" is numeric" );
else
NSLog( @"\"Not a number\" is not numeric" );
リンクを確認してください http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Objective-C 。 Swiftで試してみてください。クラス名とメソッド名は同じです。
ココアの再利用可能なメソッドは、Swift 4.1
1-クラスでファイルを作成しますNSTextFieldFormated below
2- 'Identity inspector'で、フォーマットするフィールドの 'CustomClass class'をNSTextFieldFormatedに変更します
3-「Attributes inspector」で、「int Min Value」、「int Max Value」および「int Length 'フォーマットするフィールドの
4-アウトラインインターフェイスビルダーオブジェクトリスト(左の左側)の 'オブジェクトライブラリ'から 'View Controller Scene'に 'オブジェクト'(NSObject)をドラッグアンドドロップインターフェイス描画領域)
5-「Identity inspector」で、「CustomClass class」をNSTextFieldFormatedに設定します
6-フォーマットするフィールドを選択し、Connectionsインスペクターで、フィールドデリゲートを新しい 'Text Field Formatted'の 'View Controller Scene'に設定します。
次に、NSTextFieldがフォーマットされました。
class NSTextFieldFormated: NSTextField, NSControlTextEditingDelegate {
private struct Digit {
var minValue: Int? // minimum
var maxValue: Int? // maximum
var digitAmt: Int? // minimumIntegerDigits
}
private var digit = Digit()
//-Integer
@IBInspectable var intMinValue: Int {
get {
guard let minVal = digit.minValue else { return Int.min }
return minVal
}
set { digit.minValue = newValue ; setFormatter() }
}
@IBInspectable var intMaxValue: Int {
get {
guard let maxVal = digit.maxValue else { return Int.max }
return maxVal
}
set { digit.maxValue = newValue ; setFormatter() }
}
@IBInspectable var intLenght: Int {
get {
guard let length = digit.digitAmt else { return -1 }
return length
}
set { digit.digitAmt = newValue ; setFormatter() }
}
private func setFormatter() {
let lformatter = IntegerFormatter()
lformatter.minimum = intMinValue as NSNumber
lformatter.maximum = intMaxValue as NSNumber
if intLenght != -1 {
lformatter.minimumIntegerDigits = intLenght
}
self.formatter = lformatter
}
class IntegerFormatter: NumberFormatter {
override func isPartialStringValid(_ partialString: String,
newEditingString newString: AutoreleasingUnsafeMutablePointer<NSString?>?,
errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {
if partialString.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) != nil {
NSSound.beep()
return false
}
return Int(partialString) != nil
}
}
override func controlTextDidChange(_ notification: Notification) {
if let textField = notification.object as? NSTextFieldFormated {
if let val = Int(textField.stringValue) {
//print(">4")
if val > textField.intMaxValue {
textField.stringValue = String(textField.intMaxValue)
}
}
}
}
}
IN Swift 4
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == mobileTF{
let allowingChars = "0123456789"
let numberOnly = NSCharacterSet.init(charactersIn: allowingChars).inverted
let validString = string.rangeOfCharacter(from: numberOnly) == nil
return validString
}
return true
}