Swift中如何检测Collection View Cell内所有OTP输入框是否已填写以控制发送按钮状态
Let's tackle this problem with a straightforward approach that integrates seamlessly with your existing code. Here's how to implement the logic step by step:
Step 1: Add a Storage Array for OTP Digits
First, we need a way to track the content of each OTP input field. Add an array property to your OTPViewController to store each digit, initialized to match the number of OTP fields from the server:
class OTPViewController: UITableViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITextFieldDelegate { // Add this property to track each OTP digit private var otpDigits: [String] = [] // Connect your Send button via IBOutlet @IBOutlet weak var sendButton: UIButton! override func viewDidLoad() { super.viewDidLoad() // Initialize the array once you receive otpTextCount from the server // Example: After fetching the OTP length from your API otpDigits = Array(repeating: "", count: otpTextCount) // Disable the button by default sendButton.isEnabled = false sendButton.alpha = 0.5 } // ... rest of your existing code ... }
Step 2: Update Array & Handle Input Flow
Modify your text field delegate methods to update the otpDigits array whenever a user types or deletes a character. We'll also add automatic focus switching between fields for better user experience:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // Restrict input to single digits only guard string.isEmpty || (string.count == 1 && CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: string))) else { return false } let currentText = textField.text ?? "" let newText = (currentText as NSString).replacingCharacters(in: range, with: string) // Update our tracking array with the latest text otpDigits[textField.tag] = newText // Auto-move to next field when a digit is entered if !newText.isEmpty && textField.tag < otpTextCount - 1 { let nextIndex = IndexPath(row: textField.tag + 1, section: 0) if let nextCell = collectionView.cellForItem(at: nextIndex) as? OTPCollectionViewCell { nextCell.otpTextField.becomeFirstResponder() } } // Auto-move to previous field when a digit is deleted if newText.isEmpty && textField.tag > 0 { let prevIndex = IndexPath(row: textField.tag - 1, section: 0) if let prevCell = collectionView.cellForItem(at: prevIndex) as? OTPCollectionViewCell { prevCell.otpTextField.becomeFirstResponder() } } // Update button state immediately after input changes updateSendButtonState() return true }
Step 3: Implement the Validation Logic
Add a helper method to check if all OTP fields are filled with valid digits, then update the Send button's state:
private func updateSendButtonState() { // Verify every element in otpDigits has exactly one character let allFieldsFilled = otpDigits.allSatisfy { $0.count == 1 } sendButton.isEnabled = allFieldsFilled // Adjust button opacity for visual feedback sendButton.alpha = allFieldsFilled ? 1.0 : 0.5 }
Step 4: Handle Edge Cases
Make sure to update the button state if the user taps away from the keyboard or edits fields manually:
func textFieldDidEndEditing(_ textField: UITextField) { // Sync the tracking array with the latest text in the field otpDigits[textField.tag] = textField.text ?? "" updateSendButtonState() }
Key Notes
- Ensure you connect your
sendButtonas an IBOutlet in your storyboard/XIB. - The
otpTextCountvalue must be set before initializing theotpDigitsarray (e.g., right after receiving data from your server). - The input restriction ensures only digits are entered, which is standard for OTP workflows.
This approach keeps all OTP field content centralized in an array, making validation simple and reliable. The auto-focus switching also makes the OTP entry process smoother for users!
内容的提问来源于stack exchange,提问作者Anilkumar iOS Developer

