如何解决在 UITextField
我试图在使用数字键盘输入 UITextField 时将文本格式化为 mm:ss(minutes:seconds)。问题是当点击返回删除所有文本时,这里的初始持续时间将为 00:00,然后当用户开始输入应格式化为 mm:ss 的文本时。当用户点击后退按钮时,文本应开始恢复,如下图所示。
import UIKit
import Foundation
public class DurationTextField: UITextField {
public enum Format: String {
case minuteSecond = "mm'*'ss"
}
// MARK: - Properties
private let dateFormatter = DateFormatter()
public var dateFormat = Format.minuteSecond
public var separator: String = ":"
// MARK: - Lifecycle
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private func setup() {
super.delegate = self
keyboardType = .numberPad
autocorrectionType = .no
backgroundColor = .clear
self.text = "00:00"
}
func numberOnlyString(with string: String) -> String? {
let expression = NSRegularExpression.MatchingOptions(rawValue: 0)
let range = NSRange(location: 0,length: string.count)
let digitOnlyRegex = try? NSRegularExpression(pattern: "[^0-9]+",options: NSRegularExpression.Options(rawValue: 0))
return digitOnlyRegex?.stringByReplacingMatches(in: string,options: expression,range: range,withTemplate: "")
}
}
// MARK: - UITextFieldDelegate
extension DurationTextField: UITextFieldDelegate {
public func textField(_ textField: UITextField,shouldChangeCharactersIn range: NSRange,replacementString string: String) -> Bool {
if string.count == 0 {
return true
}
guard let swiftRange = textField.text?.getRange(from: range) else {
return false
}
guard let replacedString = textField.text?.replacingCharacters(in: swiftRange,with: string) else {
return false
}
guard let numbersOnly = numberOnlyString(with: replacedString) else {
return false
}
switch dateFormat {
case .minuteSecond:
guard numbersOnly.count <= 4 else { return false }
let splitString = split(string: numbersOnly,format: [2,2])
let minutes = splitString.count > 0 ? splitString[0] : ""
let seconds = splitString.count > 1 ? splitString[1] : ""
textField.text = final(minutes: minutes,seconds: seconds)
}
return false
}
func split(string: String,format: [Int]) -> [String] {
var mutableString = string
var splitString = [String]()
for item in format {
if mutableString.count == 0 {
break
}
if mutableString.count >= item {
let index = string.index(mutableString.startIndex,offsetBy: item)
splitString.append(String(mutableString[..<index]))
mutableString.removeSubrange(Range(uncheckedBounds: (mutableString.startIndex,index)))
} else {
splitString.append(mutableString)
mutableString.removeSubrange(Range(uncheckedBounds: (mutableString.startIndex,mutableString.endindex)))
}
}
return splitString
}
func final(minutes: String,seconds: String) -> String {
var durationString = dateFormat.rawValue
durationString = durationString.replacingOccurrences(of: "mm",with: minutes)
durationString = durationString.replacingOccurrences(of: "ss",with: seconds)
if minutes.count >= 2 {
durationString = durationString.replacingOccurrences(of: "*",with: separator)
} else {
durationString = durationString.replacingOccurrences(of: "*",with: "")
}
durationString = durationString.replacingOccurrences(of: "'",with: "")
return durationString
}
}
// MARK: - String Extension
extension String {
fileprivate func getRange(from nsRange: NSRange) -> Range<String.Index>? {
guard
let from16 = utf16.index(utf16.startIndex,offsetBy: nsRange.location,limitedBy: utf16.endindex),let to16 = utf16.index(utf16.startIndex,offsetBy: nsRange.location + nsRange.length,let start = from16.samePosition(in: self),let end = to16.samePosition(in: self)
else { return nil }
return start ..< end
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。