Set a Countdown timer on Alert Controller Title text

807 Views Asked by At

I have an Alert controller which will takes minute input and show the countdown to the title of the controller and also highlighted the selected action.

enter image description here

How can I update the timer on the title, and make bold the selected Action. My Alert controller code is:-

 let actionSheet = UIAlertController(title: "Set Timer", message: "--:--", preferredStyle: .actionSheet)
    let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    
    let time10 = UIAlertAction(title: "10 Minutes", style: .default) {
        
        action in
        self.totalTime = 600
        self.startTimer()
        
    }
    
    let time20 = UIAlertAction(title: "20 Minutes", style: .default) {
        
        action in
        self.totalTime = 1200
        self.startTimer()
    }
    
    let timeCustom = UIAlertAction(title: "Custom", style: .default) {
        
        action in
        self.performSegue(withIdentifier: "customTimer", sender: nil)
        
    }
    
    
    actionSheet.addAction(time10)
    actionSheet.addAction(time20)
    actionSheet.addAction(timeCustom)
    actionSheet.addAction(cancel)
    
    present(actionSheet, animated: true, completion: nil)
    
}

// startTimer()

func startTimer() {
        
        countdownTimer?.invalidate()

            countdownTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)

    }
    @objc func updateTime() {
        
        print("update:- \(totalTime)")
        
        if totalTime != 0 {
            totalTime -= 1
        } else {
            
            endTimer()
        }
    }
    
    func endTimer() {
        print("end:- \(totalTime)")
    
        countdownTimer?.invalidate()
        
        print("timer end")
    }
2

There are 2 best solutions below

6
Ptit Xav On BEST ANSWER

Declare the action as instance property and as an alert ,update the message with the remaining time and also define the preferred action in the action in the action'action:

    let actionSheet = UIAlertController?
    var totalTime = 600
    var time10 : UIAlertAction?
    var time20 : UIAlertAction?
    var timeCustom : UIAlertAction?

And during action initialisation :

    actionSheet = UIAlertController(title: "Set Timer", message: "--:--", preferredStyle: .alert)
    time10 = UIAlertAction(title: "10 Minutes", style: .default) {
        action in
        self.totalTime = 600
        self.startTimer()
        self.actionSheet?.preferredAction = self.time10
    }

    time20 = UIAlertAction(title: "20 Minutes", style: .default) {

        action in
        self.totalTime = 1200
        self.startTimer()
        self.actionSheet?.preferredAction = self.time20
    }

    let timeCustom = UIAlertAction(title: "Custom", style: .default) {
        action in
        self.performSegue(withIdentifier: "customTimer", sender: nil)
        self.actionSheet?.preferredAction = self. and timertimeCustom
    }



@objc func updateTime() {
    
    print("update:- \(totalTime)")
    
    if totalTime != 0 {
        totalTime -= 1
    } else {        
        endTimer()
    }
    let hour = totalTime / 3600
    let minute = (totalTime - hour) / 60
    let seconds = (totalTime - hour) % 60
    actionSheet?.message = "\(hour):\(minute):\(seconds)"
}

First call : enter image description here

Second call : enter image description here

0
Y Junction On

Ptit Xav's answer is good, but it has a problem. When I open the alert for the second time app crashing.

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UIAlertController can only have one action with a style of UIAlertActionStyleCancel' terminating with uncaught exception of type NSException

Somehow I fix the problem, it is a minor fixing.

Define properties:-

let actionSheet : UIAlertController?
var totalTime = 600

var time10 : UIAlertAction?
var time20 : UIAlertAction?
var timeCustom : UIAlertAction?

Then inside the Action Function:-

func showActionSheetForSelectTimer() {
actionSheet = UIAlertController(title: "Set Timer", message: "--:--", preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
 time10 = UIAlertAction(title: "10 Minutes", style: .default) {
        action in
        self.totalTime = 600
        self.startTimer()
        self.actionSheet?.preferredAction = self.time10
    }

    time20 = UIAlertAction(title: "20 Minutes", style: .default) {

        action in
        self.totalTime = 1200
        self.startTimer()
        self.actionSheet?.preferredAction = self.time20
    }

    let timeCustom = UIAlertAction(title: "Custom", style: .default) {
        action in
        self.performSegue(withIdentifier: "customTimer", sender: nil)
        self.actionSheet?.preferredAction = self. and timertimeCustom
    }
        actionSheet?.addAction(cancel)
        actionSheet?.addAction(time10!)
        actionSheet?.addAction(time20!)
        actionSheet?.addAction(time30!)
        actionSheet?.addAction(time1!)
        actionSheet?.addAction(timeNever!)
        actionSheet?.addAction(timeCustom!)
        
        present(actionSheet!, animated: true, completion: nil)
        
    }
@objc func updateTime() {
    
    print("update:- \(totalTime)")
    
    if totalTime != 0 {
        totalTime -= 1
    } else {        
        endTimer()
    }
    let hour = totalTime / 3600
    let minute = (totalTime - hour) / 60
    let seconds = (totalTime - hour) % 60
    actionSheet.message = "\(hour):\(minute):\(seconds)"
}