[Swift3] 整数入力用UITextFieldを自作してみた
15713 ワード
イメージ
仕様
- 整数値専用のUITextField
- 文字は入力不可 ※keyboardTypeにnumberPadを指定するが、コピペ対策
- 編集終了時にカンマ編集を行い、フォーカスインでカンマを削除する
- カンマ編集する/しないはIB上でプロパティ指定可能
環境
Items | Version |
---|---|
Xcode | 8.2 |
Swift | 3.0.2 |
コード
定義
NumberTextField.swift
import UIKit
@IBDesignable
/// 数値専用UITextField
class NumberTextField: UITextField {
// MARK: - 変数
/// カンマ編集有無
private var isCommaFormat = true
/// カンマ編集有無
@IBInspectable var CommaFormat: Bool = true {
didSet {
self.isCommaFormat = CommaFormat
}
}
// MARK: - Controll Event
/// ロードされた後に呼び出される
override func awakeFromNib() {
super.awakeFromNib()
self.keyboardType = .numberPad
self.textAlignment = .right
}
// MARK: - Method
/// 入力が開始された際に呼ばれる
func beginEditing() {
guard let text = self.text else {
return
}
self.text = text.replacingOccurrences(of: ",", with: "")
}
/// 入力値が変更された場合に呼ばれる
func shouldChange(range: NSRange, string: String) -> Bool {
// 0-9以外の数字以外不可
return string.isEmpty || string.range(of: "^[0-9]+$", options: .regularExpression) != nil
}
/// 入力値が確定された場合に呼ばれる
func endEditing() {
guard let text = self.text else {
return
}
if self.isCommaFormat {
self.text = Int(text)?.withComma
}
}
}
Extentions.swift
import Foundation
/// Int拡張
extension Int {
/// カンマ付け
var withComma: String {
let decimalFormatter = DecimalFormatter()
guard let s = decimalFormatter.string(from: self as NSNumber) else {
fatalError()
}
return s
}
}
/// String拡張
extension String {
/// カンマ区切り数字のカンマどり
var noComma: Int {
if self.characters.count == 0 {
return 0
}
let decimalFormatter = DecimalFormatter()
guard let i = decimalFormatter.number(from: self) else {
preconditionFailure("NumberFormatter.number method failure!")
}
return Int(i)
}
}
/// カンマ編集制御用NumberFormatter拡張クラス
class DecimalFormatter: NumberFormatter {
override init() {
super.init()
self.locale = Locale(identifier: "ja_JP")
self.numberStyle = .decimal
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
使用例
ViewController.swift
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var numberTextField: NumberTextField!
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.numberTextField.delegate = self
self.textField.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - UITextField Delegate
/// UITextFieldの編集開始
func textFieldDidBeginEditing(_ textField: UITextField) {
if let numberTextField = textField as? NumberTextField {
numberTextField.beginEditing()
}
}
/// UITextFieldの値変更
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let numberTextField = textField as? NumberTextField {
return numberTextField.shouldChange(range: range, string: string)
}
return true
}
/// UITextFieldの編集終了
func textFieldDidEndEditing(_ textField: UITextField) {
if let numberTextField = textField as? NumberTextField {
numberTextField.endEditing()
}
}
}
課題
NumberTextField.swift
import UIKit
@IBDesignable
/// 数値専用UITextField
class NumberTextField: UITextField {
// MARK: - 変数
/// カンマ編集有無
private var isCommaFormat = true
/// カンマ編集有無
@IBInspectable var CommaFormat: Bool = true {
didSet {
self.isCommaFormat = CommaFormat
}
}
// MARK: - Controll Event
/// ロードされた後に呼び出される
override func awakeFromNib() {
super.awakeFromNib()
self.keyboardType = .numberPad
self.textAlignment = .right
}
// MARK: - Method
/// 入力が開始された際に呼ばれる
func beginEditing() {
guard let text = self.text else {
return
}
self.text = text.replacingOccurrences(of: ",", with: "")
}
/// 入力値が変更された場合に呼ばれる
func shouldChange(range: NSRange, string: String) -> Bool {
// 0-9以外の数字以外不可
return string.isEmpty || string.range(of: "^[0-9]+$", options: .regularExpression) != nil
}
/// 入力値が確定された場合に呼ばれる
func endEditing() {
guard let text = self.text else {
return
}
if self.isCommaFormat {
self.text = Int(text)?.withComma
}
}
}
Extentions.swift
import Foundation
/// Int拡張
extension Int {
/// カンマ付け
var withComma: String {
let decimalFormatter = DecimalFormatter()
guard let s = decimalFormatter.string(from: self as NSNumber) else {
fatalError()
}
return s
}
}
/// String拡張
extension String {
/// カンマ区切り数字のカンマどり
var noComma: Int {
if self.characters.count == 0 {
return 0
}
let decimalFormatter = DecimalFormatter()
guard let i = decimalFormatter.number(from: self) else {
preconditionFailure("NumberFormatter.number method failure!")
}
return Int(i)
}
}
/// カンマ編集制御用NumberFormatter拡張クラス
class DecimalFormatter: NumberFormatter {
override init() {
super.init()
self.locale = Locale(identifier: "ja_JP")
self.numberStyle = .decimal
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var numberTextField: NumberTextField!
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.numberTextField.delegate = self
self.textField.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - UITextField Delegate
/// UITextFieldの編集開始
func textFieldDidBeginEditing(_ textField: UITextField) {
if let numberTextField = textField as? NumberTextField {
numberTextField.beginEditing()
}
}
/// UITextFieldの値変更
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let numberTextField = textField as? NumberTextField {
return numberTextField.shouldChange(range: range, string: string)
}
return true
}
/// UITextFieldの編集終了
func textFieldDidEndEditing(_ textField: UITextField) {
if let numberTextField = textField as? NumberTextField {
numberTextField.endEditing()
}
}
}
ViewControllerに処理をdelegateしておきながら、NumberTextField自身のメソッドを呼ばせるのが何か気持ち悪い。
エレガントな解決方法があったらコメントをお願いします!
Author And Source
この問題について([Swift3] 整数入力用UITextFieldを自作してみた), 我々は、より多くの情報をここで見つけました https://qiita.com/y-some/items/1c7191dbf99c9d680865著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .