Anilkumar iOS Developer
Anilkumar iOS Developer

Reputation: 3755

How to detect all OTP textfields are filled or not in Collection view cell Swift

I have a screen called OTP. In that, I have set dynamic textfields using collectionview cell. I am able to fetch the user enters text from that textfields using the tag. But, I have an issue like, All four textfields filled then only I have to enable the Send button in the UI until that Send button would be disabled.

I am able to get text from textfields based on the textfield tag. But, How to detect wether all textfields filled or not from collectionview cell?

Any suggestions?

My code is below:

 class OTPViewController: UITableViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITextFieldDelegate {

    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        
        return otpTextCount //either 4 or 6 number comes from server array
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! OTPCollectionViewCell
        cell.otpTextField.tag = indexPath.row
        cell.otpTextField.delegate = self
        return cell
    }
    
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        
        textField.text = textField.text?.replacingOccurrences(of: " ", with: "")
        return true
    }
    
    func textFieldDidEndEditing(_ textField: UITextField) {
        
        var cell: OTPCollectionViewCell?
        cell = textField.superview?.superview as? OTPCollectionViewCell
        //        print(cell?.otpTextField.text as! String)
        //        print(cell?.otpTextField.tag)
    }

Upvotes: 1

Views: 312

Answers (2)

Anilkumar iOS Developer
Anilkumar iOS Developer

Reputation: 3755

I have found following way and it worked fine.

    private var arrayOfCells: [OTPCollectionViewCell] = []
    var insertedValues = [String]()

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! OTPCollectionViewCell
        cell.otpTextField.tag = indexPath.row
        cell.otpTextField.delegate = self
        arrayOfCells += [cell]
        return cell
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        
        if insertedValues.count > 0 {
            insertedValues.removeAll()
        }
        
        for i in 0..<arrayOfCells.count {
            if let textfieldText = arrayOfCells[i].otpTextField.text, textfieldText != "" {
                insertedValues.append(textfieldText)
                if insertedValues.count == 4 //otpTextCount{
                    nextButton.isUserInteractionEnabled = true
                }
            } else {
                nextButton.isUserInteractionEnabled = false
                
            }
    }
}

Upvotes: 0

Anton Ogarkov
Anton Ogarkov

Reputation: 455

I would recommend you to store text that were inserted into UITextFields into some sort of dictionary [Int: String] where key is the tag of cell. Then if the dictionary contains all necessary tags we can enable the button.

The example follows. I personally would recommend storing states in something like a ViewModel and moving that logic there. But this is a sample code that I did not compile, its purpose it to simply show the idea.

class OTPViewController: UITableViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITextFieldDelegate {
  var insertedValues = [Int: String]()

  func numberOfSections(in collectionView: UICollectionView) -> Int {
      return 1
  }

  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    
      return otpTextCount //either 4 or 6 number comes from server array
  }

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
      let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! OTPCollectionViewCell
      cell.otpTextField.tag = indexPath.row
      cell.otpTextField.delegate = self
      return cell
  }

  func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    
      textField.text = textField.text?.replacingOccurrences(of: " ", with: "")
      return true
  }

  func textFieldDidEndEditing(_ textField: UITextField) {
    
      guard let cell = textField.superview?.superview as? OTPCollectionViewCell else {
          assertionFailure("Orphan textField did end editing. No cell found")
          return
      } 

      if textField.text == "" {
          insertedValues[cell.tag] = nil
      } else {
          insertedValues[cell.tag] = textField.text
      }

      theButton.isEnabled = areAllFieldsFilled()
      //        print(cell?.otpTextField.text as! String)
      //        print(cell?.otpTextField.tag)
  }

  func areAllFieldsFilled() -> Bool {
      for n in 0..<otpTextCount {
          if !insertedValues.keys.contains(n) {
             return false
          }
      }

      return true
  }

Upvotes: 1

Related Questions