Home > Software engineering >  Resend OTP timer functionality in Swift
Resend OTP timer functionality in Swift

Time:08-13

I want to set a timer of 30 seconds to send an OTP to a phone number. And while the timer is running, the resend OTP button should be disabled. Once the timer ends, the resend OTP button should get enabled and the timer label should be hidden. Onclick of the resend OTP button, the same process should continue.

In the code that I have written, the timer label is hidden the entire time and is constantly going into the if loop where it is constantly printing "invalidated".

Below is the code that I have written.

Updated Code:

    @IBOutlet weak var timerLabel: UILabel!
    @IBOutlet weak var resendOTPBtn: UIButton!

  var countdownTimer: Timer!
    var totalTime = 30

 override func viewDidLoad() {
        super.viewDidLoad()
 if AFWrapper.isConnectedToInternet() {
            timerLabel.text = ""
            sendOTPCode()
            sendOTPAPICall()
        resendOTPBtn.isEnabled = false
        } else {
            self.textPopupAlert(title: ALERT_TITLE, message: OFFLINE_MSG)
        }
}

  // in case user closed the controller
     deinit {
         countdownTimer.invalidate()
     }
    
    @objc func updateTimerLabel() {
        totalTime -= 1
        timerLabel.text = "\(timeFormatted(totalTime))"
       if totalTime == 0 {
           timerLabel.text = ""
           countdownTimer.invalidate()
           resendOTPBtn.isEnabled = true

       }

     }

  @IBAction func resendOTPBtnClicked(_ sender: Any) {
        if AFWrapper.isConnectedToInternet() {
            sendOTPAPICall()
            timerLabel.text = ""
            totalTime = 31
            resendOTPBtn.isEnabled = false
            sendOTPCode()
        }
        else {
            self.textPopupAlert(title: ALERT_TITLE, message: OFFLINE_MSG)
        }

    }


func sendOTPCode() {
          self.countdownTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.updateTimerLabel), userInfo: nil, repeats: true)
}

Initial Code:

@IBAction func resendOTPBtnClicked(_ sender: Any) {
        if AFWrapper.isConnectedToInternet() {
            sendOTPAPICall()
            countDownTime()
        }
        else {
            self.textPopupAlert(title: ALERT_TITLE, message: OFFLINE_MSG)
        }

    }





func countDownTime() {
        DispatchQueue.main.asyncAfter(deadline: .now()   60) {
                self.timerLabel.isHidden = false
            self.resendOTPBtn.isEnabled = false
        if self.timerLabel.isHidden == false {
            self.startTimer()
        } else {
            self.countdownTimer.invalidate()
            self.resendOTPBtn.isEnabled = true
            self.timerLabel.isHidden = true

        }
        }

    }





 // Method to start the timer when resend OTP button is clicked.
    func startTimer() {
            countdownTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
        
        }
    


    @objc func updateTime() {
        DispatchQueue.main.async(){
            self.timerLabel.text = self.timeFormatted(self.totalTime)
                if self.totalTime != 0 {
                self.totalTime -= 1
            } else {
                print("Invalidated")
                self.endTimer()

            }
    }
        }


 func timeFormatted(_ totalSeconds: Int) -> String {
            let seconds: Int = totalSeconds % 60
            let minutes: Int = (totalSeconds / 60) % 60
            //     let hours: Int = totalSeconds / 3600
            return String(format: "d:d", minutes, seconds)
        }

Any solutions would be appreciated. Thank you!

CodePudding user response:

@IBOutlet weak var resendCodeTimerLabel: UILabel!
  @IBOutlet weak var resendCodeButton: UIButton!
  var resendCodeCounter = 30
  var resendCodeTimer = Timer()
  override func viewDidLoad() {
    super.viewDidLoad()
    resendCodeTimerLabel.text = ""
    sendOTPCode()
  }
 // in case user closed the controller
  deinit {
    resendCodeTimer.invalidate()
  }
  @objc func updateTimerLabel() {
    resendCodeCounter -= 1
    resendCodeTimerLabel.text = "Resend code in \(resendCodeCounter) seconds."
    if resendCodeCounter == 0 {
      resendCodeButton.isEnabled = true
      resendCodeTimer.invalidate()
    }
  }
  @IBAction func resendAgainButtonClicked(_ sender: UIButton) {
    OTPTextField.text = ""
    resendCodeCounter = 31
    resendCodeButton.isEnabled = false
    sendOTPCode()
  }
func sendOTPCode() {
//Whatever your api logic
        if otpSent {
          self.resendCodeTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.updateTimerLabel), userInfo: nil, repeats: true)
        }
}
  • Related