iOS15中drawText(in:)废弃后如何更新UITextField自定义实现
iOS15+ 恢复UITextField自定义2FA字符背景功能的方案
方案1:最小改动兼容方案
- 苹果仅将
drawText(in:)标记为废弃状态,未做实际功能移除,截至iOS17版本该方法仍可正常调用,原有逻辑可以直接正常运行,仅需忽略Xcode的废弃告警即可。 - 若需消除告警,可在重写的
drawText(in:)方法前添加@available(iOS, deprecated: 15.0)标记。
方案2:官方推荐的替换实现
iOS15起官方推荐使用通用绘制方法结合文本位置API实现相同效果,替换逻辑如下:
- 重写
draw(_ rect: CGRect)方法,先调用父类实现完成基础文本绘制 - 借助
UITextPosition、UITextRange相关API获取每个字符的实际占位frame,基于该frame绘制自定义背景即可,和原有drawText(in:)中的背景绘制逻辑完全通用 - 示例代码:
override func draw(_ rect: CGRect) { super.draw(rect) guard let text = text, !text.isEmpty else { return } // 遍历每个字符计算位置 for charIndex in 0..<text.count { guard let startPos = position(from: beginningOfDocument, offset: charIndex), let endPos = position(from: startPos, offset: 1), let range = textRange(from: startPos, to: endPos) else { continue } let charFrame = firstRect(for: range) // 此处复用你原有绘制单个字符背景的逻辑 let backgroundPath = UIBezierPath(roundedRect: charFrame, cornerRadius: 6) UIColor.systemGray5.setFill() backgroundPath.fill() } }
- 文本变更时调用
setNeedsDisplay()触发重绘即可,可通过监听editingChanged事件实现自动触发。
方案3:跨版本稳定实现(无API依赖)
如果不想受系统API变更影响,可以换实现思路:
- 在自定义UITextField中添加与验证码位数对应的UILabel/UIView作为单独的字符展示和背景容器
- 隐藏原生文本显示,拦截输入事件后将字符依次赋值给对应位置的容器即可,适配所有iOS版本。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

