電卓みたいなについて
以下のようなキー操作に対し、以下のような補完と入力制限をすることを目指しました。
キーボードタイプは"."と半角数字のみ入力可能な.decimalPadにします。
キー操作 → 表示
"00123" → "123" ".123" → "0.123" "0.123.123" → "0.123123"
ペースト値 → 表示
"00123" → "123" ".123" → "0.123" "0.123.123" → ペーストが行われる前の状態 "あいうえお" → ペーストが行われる前の状態 "0.123" → ペーストが行われる前の状態
大丈夫だとは思いますがこれ以外にも対応が必要なケースがあるかもしれません。
電卓みたいな動きするTextField書いた pic.twitter.com/SSEZ1RhVGH
— めも (@__zz2_) April 21, 2024
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 { // "0"から始まる文字列 while filteredText.hasPrefix("0") && filteredText.count >= 2 { // 2番目の文字を取得 let index = filteredText.index(filteredText.startIndex, offsetBy: 1) let character = filteredText[index] // "."が2番目に存在する場合を除き、先頭の文字を消去 if (character == ".") { break; } else { filteredText = String(filteredText.dropFirst()) } } // "."が先頭にのみある文字列 if filteredText.hasPrefix(".") { filteredText = "0" + filteredText // 先頭に0を追加 } self.inputValue = filteredText } } //.onChangeここまで } // bodyここまで } // ContentViewここまで
文字列から数字だけをとり出す方法
isNumberでも数字かどうかを調べることができますが、全角数字が含まれてしまい望ましくなかったので"0123456789"が含まれるか調べることにしました。
全角数字が含まれる
var filteredText = newValue.filter { $0.isNumber || $0 == "."}
全角数字が含まれない
var filteredText = newValue.filter { "0123456789.".contains($0) }
onChange(of:perform:)' was deprecated in iOS 17.0: Use onChange
with a two or zero parameter action closure instead.
廃止された古い方のonChangeを使用したので、Minimum DeploymentをiOS17.0以上にすると黄色の警告がでます。
作った理由
TextFieldに入力した金額をDBに追加する前のバリデーションとして作りました。
TextFieldに数値型の変数を渡しフォーマットを.numberにする方法は、見た目上でTextFieldにペーストや入力できてしまうので使いませんでした。