微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 UITextField

如何解决在 UITextField

我试图在使用数字键盘输入 UITextField 时将文本格式化为 mm:ss(minutes:seconds)。问题是当点击返回删除所有文本时,这里的初始持续时间将为 00:00,然后当用户开始输入应格式化为 mm:ss 的文本时。当用户点击后退按钮时,文本应开始恢复,如下图所示。

Duration TextField


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 举报,一经查实,本站将立刻删除。