-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTextFieldWithLimit
More file actions
127 lines (112 loc) · 4.63 KB
/
Copy pathTextFieldWithLimit
File metadata and controls
127 lines (112 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import UIKit
// MARK: View/TextField/BaseTextFeild.swift
/**
+ カスタムテキストフィールド基底クラス
*/
@IBDesignable
class BaseTextField: UITextField, UITextFieldDelegate, CustomViewProtocol {
// MARK: Enumerations
/// テキストフィールド受け入れる文字の正規表現式
///
enum RegularExpression: String {
/// 数字のみ
case number = "^[0-9]+$"
/// 英数字
case alphanumeric = "^[a-zA-Z0-9]+$"
/// 英数字記号
case alphanumericSymbols = "^[A-Za-z0-9!\"#$%&'()*+,.\\/:;<=>?@[\\]^_`{|}~-]+$]"
}
// MARK: Properties
/// テキストフィールド受け入れる文字の最大サイズ
var maxLength: Int?
/// テキストフィールド受け入れる文字の正規表現式
var regularExpressionFiter: RegularExpression?
/// Return(Next) keyを押した際のターゲットテキストフィールド(デフォルトの場合はキーボードを閉じる)
var nextTextField: UITextField?
// MARK: Methods
/// ソース側の初期化メソッド
///
/// - Parameter frame: ビューの初期化範囲
override init(frame: CGRect) {
super.init(frame: frame)
setLimitEvent()
}
/// Storyboard或いはXib側の初期化メソッド
///
/// - Parameter aDecoder:Storyboard或いはXib側にあるのビューの初期化設定
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
setLimitEvent()
}
/// 入力制限のデリゲートと通知を設定する
func setLimitEvent() {
delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidChange), name: NSNotification.Name.UITextFieldTextDidChange, object: self)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
/// テキストフィールドの属性を設定する処理
func setStyle() {
// これを設定しないと自動設定と衝突して無限ループする可能性がある。
self.adjustsFontSizeToFitWidth = false
}
/// ボタンの描画メソッド
///
/// - Parameter rect: ボタンのサイズ
override func draw(_ rect: CGRect) {
super.draw(rect)
setStyle()
}
/// 入力制限を付けるデリゲート
///
/// - Parameters:
/// - textField: 入力しているtextField
/// - range: 選択された文字列の範囲
/// - string: 入力された文字列
/// - Returns: 今回の入力が有効かどうか(true時は有効)
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let str = textField.text! + string
if let maxLength = maxLength, str.count > maxLength {
return false
}
guard let regularExpressionFiter = regularExpressionFiter else {
return true
}
let isInRegularExpressionFiter = string.range(of: regularExpressionFiter.rawValue, options: .regularExpression) != nil
// undoでクラッシュしてしまうのを防止する
let undoStr = textField.undoManager!.undoActionName
if undoStr == "Paste" && !isInRegularExpressionFiter {
textField.undoManager?.removeAllActions()
}
return string.isEmpty || isInRegularExpressionFiter
}
/// 入力制限を付ける通知メソッド
///
/// - Parameter notification: 通知オブジェクト
@objc private func textFieldDidChange(notification: NSNotification) {
guard let regularExpressionFiter = regularExpressionFiter else {
return
}
guard let curText = self.text else {
return
}
if curText.range(of: regularExpressionFiter.rawValue, options: .regularExpression) == nil {
var tmpText = ""
curText.forEach { $0.description.range(of: regularExpressionFiter.rawValue, options: .regularExpression) != nil ? tmpText.append($0) : tmpText.append("") }
self.text! = tmpText
}
}
/// デリゲートを指定されたTextFieldのキーボードのReturnボタンを押した時の動作を指定する(プロトコルメソッド)
///
/// - Parameter textField: 対象のTextField
/// - Returns: Return(完了、Next)ボタンを押す動作が有効かどうか
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let nextTextField = nextTextField {
nextTextField.becomeFirstResponder()
} else {
resignFirstResponder()
}
return true
}
}