在開發過程中,我們經常遇到這樣的需求,需要對textField的輸入做限制(限制只能輸入中文,英文,數字),如果是英文和數字還簡單些,中文的話大家做的時候可能就會發現問題了,如果我們使用shouldChangeCharacters處理的話是無法實現的,因為輸入法輸入中文的時候會首先把輸入的拼音(叫做:marked text)顯示在輸入框中,然后點擊鍵盤候選區的中文之后才會把中文顯示在textfield中。
這時我們就不能使用這種方法了,我們要監聽textField的UITextFieldTextDidChangeNotification來實現,這種方法實現的基本思路:
1.先判斷當前是否有 markedtext,有的話我們不做任何動作。
2.使用正則過濾掉 textField 里非中文的字符,然后再將結果重新賦給 textField。
3.進行上面操作前要記下光標的位置,在賦值后再還原光標位置。否則如果在中間輸入文字后,光標會自動跳到末尾。
// // ViewController.swift // // // Created by 黃鎮威 on 2018/1/9. // Copyright © 2018年 黃鎮威. All rights reserved. // import UIKit class ViewController: UIViewController { //文本輸入框 var textField:UITextField! override func viewDidLoad() { super.viewDidLoad() //初始化文本輸入框 textField = UITextField(frame: CGRect(x:20, y:100, width:200, height:30)) textField.borderStyle = .roundedRect self.view.addSubview(textField) } override func viewDidAppear(_ animated: Bool) { //監聽textField內容改變通知 NotificationCenter.default.addObserver(self, selector: #selector(self.greetingTextFieldChanged), name:NSNotification.Name(rawValue:"UITextFieldTextDidChangeNotification"), object: self.textField) } //textField內容改變通知響應 @objc func greetingTextFieldChanged(obj: Notification) { //非markedText才繼續往下處理 guard let _: UITextRange = textField.markedTextRange else{ //當前光標的位置(后面會對其做修改) let cursorPostion = textField.offset(from: textField.endOfDocument, to: textField.selectedTextRange!.end) //判斷非中文的正則表達式 let pattern = "[^\\u4E00-\\u9FA5]" // 非中文:[^\\u4E00-\\u9FA5] // 非英文:[^A-Za-z] // 非數字:[^0-9] // 非中文或英文:[^A-Za-z\\u4E00-\\u9FA5] // 非英文或數字:[^A-Za-z0-9] //替換后的字符串(過濾調非中文字符) var str = textField.text!.pregReplace(pattern: pattern, with: "") //限制文字長度不能超過10個 if str.count > 10 { str = String(str.prefix(10)) } textField.text = str //讓光標停留在正確位置 let targetPostion = textField.position(from: textField.endOfDocument, offset: cursorPostion)! textField.selectedTextRange = textField.textRange(from: targetPostion, to: targetPostion) return } } override func viewDidDisappear(_ animated: Bool) { //移除textField內容改變通知監聽 NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "UITextFieldTextDidChangeNotification"), object: self.textField) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
extension String { //使用正則表達式替換 func pregReplace(pattern: String, with: String, options: NSRegularExpression.Options = []) -> String { let regex = try! NSRegularExpression(pattern: pattern, options: options) return regex.stringByReplacingMatches(in: self, options: [], range: NSMakeRange(0, self.count), withTemplate: with) } }