電卓みたいなについて
以下のようなキー操作に対し、以下のような補完と入力制限をすることを目指しました。
キーボードタイプは"."と半角数字のみ入力可能な.decimalPadにします。
キー操作 → 表示
"00123" → "123"
".123" → "0.123"
"0.123.123" → "0.123123"
ペースト値 → 表示
"00123" → "123"
".123" → "0.123"
"0.123.123" → ペーストが行われる前の状態
"あいうえお" → ペーストが行われる前の状態
"0.123" → ペーストが行われる前の状態
大丈夫だとは思いますがこれ以外にも対応が必要なケースがあるかもしれません。
ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var inputValue = ""
var body: some View {
TextField("数値を入力してください", text: $inputValue)
.keyboardType(.decimalPad)
.onChange(of: inputValue) { [inputValue] newValue in
var filteredText = newValue.filter { "0123456789.".contains($0) }
let dotIndices = filteredText.indices.filter { filteredText[$0] == "." }
if dotIndices.count > 1 {
self.inputValue = inputValue
} else {
while filteredText.hasPrefix("0") && filteredText.count >= 2 {
let index = filteredText.index(filteredText.startIndex, offsetBy: 1)
let character = filteredText[index]
if (character == ".") {
break;
} else {
filteredText = String(filteredText.dropFirst())
}
}
if filteredText.hasPrefix(".") {
filteredText = "0" + filteredText
}
self.inputValue = filteredText
}
}
}
}
文字列から数字だけをとり出す方法
isNumberでも数字かどうかを調べることができますが、全角数字が含まれてしまい望ましくなかったので"0123456789"が含まれるか調べることにしました。
全角数字が含まれる
var filteredText = newValue.filter { $0.isNumber || $0 == "."}
全角数字が含まれない
var filteredText = newValue.filter { "0123456789.".contains($0) }
廃止された古い方のonChangeを使用したので、Minimum DeploymentをiOS17.0以上にすると黄色の警告がでます。
作った理由
TextFieldに入力した金額をDBに追加する前のバリデーションとして作りました。
TextFieldに数値型の変数を渡しフォーマットを.numberにする方法は、見た目上でTextFieldにペーストや入力できてしまうので使いませんでした。