在開發過程中,我們經常遇到這樣的需求,需要對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)
}
}
