惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
T
The Blog of Author Tim Ferriss
GbyAI
GbyAI
雷峰网
雷峰网
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
F
Fortinet All Blogs
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tailwind CSS Blog
Y
Y Combinator Blog
J
Java Code Geeks
S
SegmentFault 最新的问题
罗磊的独立博客
爱范儿
爱范儿
F
Full Disclosure
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
V2EX
G
Google Developers Blog
腾讯CDC
美团技术团队
Martin Fowler
Martin Fowler
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
D
DataBreaches.Net
大猫的无限游戏
大猫的无限游戏
博客园 - 【当耐特】
B
Blog
Recorded Future
Recorded Future
月光博客
月光博客
Blog — PlanetScale
Blog — PlanetScale
IT之家
IT之家
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
云风的 BLOG
云风的 BLOG
博客园 - 聂微东
阮一峰的网络日志
阮一峰的网络日志
B
Blog RSS Feed
aimingoo的专栏
aimingoo的专栏
W
WeLiveSecurity
Recent Announcements
Recent Announcements
P
Palo Alto Networks Blog
Apple Machine Learning Research
Apple Machine Learning Research
MongoDB | Blog
MongoDB | Blog
G
GRAHAM CLULEY
A
Arctic Wolf
AWS News Blog
AWS News Blog
Project Zero
Project Zero
博客园 - Franky
V
Vulnerabilities – Threatpost

木土金王可

复盘 2024,年度好物分享 落地 第二十台相机:宝丽来(Polaroid)Impulse AF 第十九台相机:哈苏(Hasselblad)X1D II 第十八台相机:宝丽来(Polaroid)Macro 5 SLR 第十七台相机:康泰时(Contax)S2 稻荷山 Dave Chappelle: The Closer 语言是思想的边界 对街头卖惨表演的看法 《民主森林》 电梯英雄 2023,年度好物分享 《大画幅 4x5》复活 新加坡华侨银行(OCBC)开户指南 第十六台相机:宾得(Pentax)PC35AF-M SEDATE 第十五台相机:沙慕尼(Chamonix)4x5 F2 Xbox 连接 Studio Display Twitter、Apple、Meta 和 Reddit 广告平台使用体验 第十四台相机:康泰时(Contax)S2 你到底什么时候买相机 拍摄胶片的理由 HomePod 不能作为 Mac 音响 男性生来就是残缺的女性 第十三台相机:柯尼卡(Konica)Big Mini 301 三年,十二台相机 恐怖片很好看啊 比残忍更残忍 用 SwiftUI 重构「行动日」 推荐《女生呵护指南》 你是左派还是右派? 驯服内心的猛犸象:为什么你应该停止关心别人对你的想法 想写点什么,但又不知道该写什么 摄影构图 精致的结婚照 中文没死,是有的人死了 上海爆发 COVID-19 疫情以来我收藏的文章(持续更新) 自我审查 25 美元,成为美国计算机学会(ACM)会员 将同事送我的仙人掌转换成 3D 模型 当我们谈论离屏渲染时,我们在谈论什么 如何让 iOS 给你的应用开后门 二零一九年夏秋之交工作生活的异动 一声一世 对于番茄学习法的误解 Swift 中的空字符串 我如何自学 iOS 开发 为什么我不喜欢社交网络 如何与人见面 为什么我不喜欢即时通讯 以配置信息(UserDefaults)的形式存储应用数据 在文件沙盒中读取与写入应用数据 在 iOS 开发中使用键值对监听(KVO)与通知(Notification) 介绍 GCD 中的线程,队列,延迟执行,线程阻断,信号量,任务组与任务对象 iOS 原生 URLSession 网络请求 什么是自动引用计数(ARC)和引用循环 在 iOS 开发中使用代理与协议 独立开发的第一个应用:行动日 为什么我会把 Google Pixel 换成 iPhone SE? 手动进行 Nexus 和 Pixel 系列手机的 OTA 更新 开启 Chromebook 的夜间模式
iOS 限制输入字数与特殊字符的巧妙方法
kinnouka bokudo · 2019-06-22 · via 木土金王可

在 iOS 开发中,时常需要限制用户的输入行为,比如限制用户只能输入数字,或是只能输入中文、英文等等。虽说可以通过设置键盘类型来简单规避掉一些不必要的麻烦,但本文将着重从代码层面以 UITextField 为例,介绍如何限制输入字数与特殊字符。

添加监听事件

限制 UITextField 输入内容的第一步就是得知 UITextField 中内容的变化。我们可以通过以下代码为 textField 添加监听事件:

private let textField = UITextField()

override func viewDidLoad() {
    super.viewDidLoad()
    self.textField.addTarget(self, action: #selector(textFieldDidEdit), for: .editingChanged)
    ...
}

@objc private func textFieldDidEdit() {
    ...
}

textField 中的内容发生变化时,将会调用 textFieldDidEdit() 方法。动态监听 textField 内容变化不仅可以限制用户手动输入的内容,还可以限制复制粘贴的内容。

补全监听事件

在补全此监听事件前,还需定义一个全局变量 qualifiedString,代码如下:

private var qualifiedString = ""

该变量用来暂存 textField 中的符合条件的内容,当 textField 中所输入的内容符合条件时,我们不对 textField 进行输入限制,并同时将 textField 中的内容赋值给 qualifiedString,而当 textField 中所输入的内容不符合条件时,对 textField 的输入进行限制,即用户输入无效,并将 qualifiedString 作为 textField 中的内容保持不变。textFieldDidEdit() 方法完整代码如下:

@objc private func textFieldDidEdit() {
    // 1
    guard self.textField.markedTextRange == nil else { return }

    // 2
    guard let text = self.textField.text, text.isEmpty == false else {
        self.qualifiedString = ""
        return
    }

    // 3
    if self.isIncludeSpecialCharacters(in: text) || self.isBeyondNumberOfMaxInput(in: text) {
    self.textField.text = self.qualifiedString

    } else {
        self.qualifiedString = text
    }
}

接下来我将一步步解释这些代码的作用:

  1. 判断 textField 是否存在高亮区域,即当用户使用拼音等输入法进行输入时,还没有确定输入选词,拼写时的产生英文不算入输入内容。
  2. 判断 textField 中是否有内容,只有当 textField 中存在内容时代码才会继续运行。
  3. 代码运行到这里将会报错,因为我们还未定义 isIncludeSpecialCharacters(in: String)isBeyondNumberOfMaxInput(in: String) 方法,后文将会介绍这些的方法的定义以及实现。这段代码会判断 textField 中是否包含特殊字符,或者 textField 中的内容长度是否超过所定义的最大输入数量,如果 textField 中的内容满足上述任意条件,则 qualifiedString 替代 textField 中的内容;否则视 textField 中的内容符合条件,并对 qualifiedString 赋值。

处理特殊字符

本文假设中文、英文以外的所有字符皆为特殊字符。于是使用正则表达式对 textField中的对每一个字符进行判别,并计算特殊字符数量 numberOfCharacters,只要当 numberOfCharacters 不为零即视为存在特殊字符。代码如下:

private func isIncludeSpecialCharacters(in string: String) -> Bool {
    let pattern = "[^A-Za-z\\u4E00-\\u9FA5\\d]"
    let expression = try! NSRegularExpression(pattern: pattern, options: .allowCommentsAndWhitespace)
    let numberOfCharacters = expression.numberOfMatches(in: string, options: .reportProgress, range: NSMakeRange(0, (string as NSString).length))

    return numberOfCharacters == 0 ? false : true
}

处理输入数量限制

本文假设最大输入数量限制为 16 个英文字符或 8 个中文字符,一个中文字符相当于两个英文字符。而在不同编码的字符系统中,中文、英文长度都不同,所以定义变量 count用来表示中文、英文的字符个数,并以此与最大输入数量进行比较。代码如下:

private func isBeyondNumberOfMaxInput(in string: String) -> Bool {
    var count = 0

    for char in string {
        let lengthOfCharacter = "\(char)".lengthOfBytes(using: .utf8)

        // 英文
        if lengthOfCharacter == 1 {
            count = count + 1
        }

        // 中文
        else if lengthOfCharacter == 3 {
            count = count + 2
        }
    }

    return count <= 16 ? false : true
}

注意事项

虽说以上代码已满足限制输入字数与特殊字符的基本要求,但当用户复制的内容中包含特殊字符,或是复制粘贴后字数超出最大输入限制的话,会导致用户所复制的内容完全无法粘贴到 textField 中。解决这个问题的办法是,将是否包含特殊字符与是否超出最大输入限制分开判断,并分别处理。例如,当 textField 中的内容包含特殊字符时,可以只删除掉特殊字符后,再将 textField 中的内容赋值给 qualifiedString,当 textField 中的内容超出最大输入限制时,按最大输入限制截取 textField 中的内容并赋值给 qualifiedString,具体代码因为我懒就不再展示。

2019 年 6 月 22 日