Swift 4:多UITextField数字分段字体设置及逆向计算实现
Alright, let's break down how to implement this dynamic font switching for your UITextFields exactly as you described. I'll walk you through each step with code examples that work in real-time during input.
1. Prepare Your Custom Fonts
First, make sure your font1 and font2 are properly added to your Xcode project and registered in your Info.plist under the Fonts provided by application key. Then load them once (preferably in your view controller's viewDidLoad):
class YourViewController: UIViewController, UITextFieldDelegate { // Load fonts once with fixed 50pt size private let largeFont = UIFont(name: "YourFont1Name", size: 50)! private let regularFont = UIFont(name: "YourFont2Name", size: 50)! // Connect your three UITextFields via IBOutlets @IBOutlet weak var textField1: UITextField! @IBOutlet weak var textField2: UITextField! @IBOutlet weak var textField3: UITextField! override func viewDidLoad() { super.viewDidLoad() // Configure all text fields [textField1, textField2, textField3].forEach { $0?.delegate = self $0?.keyboardType = .numberPad $0?.textAlignment = .left // Adjust alignment as needed // Initialize font state updateTextFieldFont($0!) } } }
2. Real-Time Font Formatting Logic
The core of this feature is updating the attributed text as the user types. We'll use the UITextFieldDelegate to intercept input changes and apply the font rules:
// MARK: - UITextFieldDelegate extension YourViewController { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // Only allow numeric input let allowedChars = CharacterSet.decimalDigits guard allowedChars.isSuperset(of: CharacterSet(charactersIn: string)) else { return false } // Calculate the new text after the change let currentText = textField.text ?? "" let newText = (currentText as NSString).replacingCharacters(in: range, with: string) // Enforce input range limits (0-13066 or 0-3915) let maxValue: Int = textField == textField3 ? 3915 : 13066 if !newText.isEmpty, let num = Int(newText), num > maxValue { return false } // Update the text field's plain text first, then apply font formatting textField.text = newText updateTextFieldFont(textField) // Return false because we've manually handled the text update return false } func textFieldShouldClear(_ textField: UITextField) -> Bool { updateTextFieldFont(textField) return true } } // MARK: - Font Update Helper extension YourViewController { private func updateTextFieldFont(_ textField: UITextField) { guard let text = textField.text, !text.isEmpty else { textField.attributedText = nil return } let attributedString = NSMutableAttributedString(string: text) if text.count > 3 { // Apply large font to the thousands place (first character) attributedString.addAttribute( .font, value: largeFont, range: NSRange(location: 0, length: 1) ) // Apply regular font to hundreds, tens, and ones places attributedString.addAttribute( .font, value: regularFont, range: NSRange(location: 1, length: text.count - 1) ) } else { // All digits use regular font for values < 1000 attributedString.addAttribute( .font, value: regularFont, range: NSRange(location: 0, length: text.count) ) } textField.attributedText = attributedString } }
3. Reverse Calculation (Extract Numeric Value)
If you need to retrieve the raw numeric value from the formatted attributed text, just extract all numeric characters (ignoring font styling):
func extractNumericValue(from textField: UITextField) -> Int? { guard let attributedText = textField.attributedText else { return nil } let plainText = attributedText.string let digitString = plainText.filter { $0.isNumber } return Int(digitString) }
4. Edge Cases Handled
- Empty text fields: Clears attributed text properly
- Values < 1000: Uses
font2for all digits - Values ≥ 1000: Automatically switches the first digit to
font1 - Input limits: Blocks values exceeding 13066 or 3915 depending on the text field
- Backspace/delete: Updates font formatting in real-time as digits are removed
内容的提问来源于stack exchange,提问作者ScoobyDooku

