Home > Mobile >  ViewController doesn't pass data on completion
ViewController doesn't pass data on completion

Time:11-15

I have 2 ViewControllers.

TimerViewController passes a variable to the EditTimerViewConroller. EditTimerViewConroller edits it and should pass it back, but it looks like code in .completion is not executed.

Any advice how to fix it?

My code is:

TimerViewController

import UIKit
import AVFoundation //play sounds

class TimerViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()   
    }
    
    var player: AVAudioPlayer!
    var timer = Timer()
    var totalTime = 10.0
    var secondsRemaining = 10.0
    var secondsPassed = 0.0
    let timerStep = 0.1

    @IBOutlet weak var timerLabel: UILabel!
    
    
    @IBOutlet weak var progressBar: UIProgressView!
    
    @IBAction func startPressed(_ sender: UIButton) {
        //works fine
    }
    
    @IBAction func editTimerButtinPresed(_ sender: UIButton) {
        self.performSegue(withIdentifier: "goToEditTimer", sender: self)
        
        let editTimer = EditTimerViewController()
        editTimer.completion = { [weak self] duration in
            DispatchQueue.main.async {
                self?.totalTime = Double(duration!)
                print("editTimer completed, totalTime now is \(self?.totalTime)")
            }
        }
    }
    
    func playSound(fileName: String) {
        //works fine
    }
    
    @objc func updateTimer() {
        //works fine
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goToEditTimer" {
            let destinationVC = segue.destination as! EditTimerViewController
            destinationVC.duration = Int(totalTime)
            print("Pasing duration = \(totalTime) to Edit screen")
        }
    }

EditTimerViewController

import UIKit

class EditTimerViewController: UIViewController {
    
    let maxDuration = 60
    var duration: Int? //timer duraton is passed from Timer
    public var completion: ((Int?) -> Void)?

    override func viewDidLoad() {
        super.viewDidLoad()
        durationSlider.minimumValue = 0
        durationSlider.maximumValue = Float(maxDuration)
        durationSlider.value = Float(duration!)
        
        durationLabel.text = String(duration!)   "s"
        }
    
    @IBOutlet weak var durationLabel: UILabel!
    @IBOutlet weak var durationSlider: UISlider!
    
    @IBAction func durationSliderChanged(_ sender: UISlider) {
        duration = Int(sender.value)
        print(duration!)
        durationLabel.text = String(duration!)   "s"
    }
    
    @IBAction func cancelPressed(_ sender: UIButton) {
        print("Cancel pressed, dismissing Edit screen")
        self.dismiss(animated: true, completion: nil)
    }
    
    @IBAction func savePressed(_ sender: UIButton) {
        print("Save pressed, duration is \(duration!)")
        completion?(duration!)
        self.dismiss(animated: true, completion: nil)

    }
}

In the output after pressing Save button I see

Save pressed, duration is 11

but after it there is no sign of

editTimer completed, totalTime now is 11

and timer duration never changes

CodePudding user response:

Change

@IBAction func editTimerButtinPresed(_ sender: UIButton) {
    self.performSegue(withIdentifier: "goToEditTimer", sender: self)
    
    let editTimer = EditTimerViewController()
    editTimer.completion = { [weak self] duration in
        DispatchQueue.main.async {
            self?.totalTime = Double(duration!)
            print("editTimer completed, totalTime now is \(self?.totalTime)")
        }
    }
}

To

@IBAction func editTimerButtinPresed(_ sender: UIButton) {
    self.performSegue(withIdentifier: "goToEditTimer", sender: self) 
}

And move completion inside prepare

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "goToEditTimer" {
        let destinationVC = segue.destination as! EditTimerViewController
        destinationVC.duration = Int(totalTime)
        print("Pasing duration = \(totalTime) to Edit screen")
        destinationVC.completion = { [weak self] duration in
            DispatchQueue.main.async {
                self?.totalTime = Double(duration!)
                print("editTimer completed, totalTime now is \ (self?.totalTime)")
            }
         }
     }
}
  • Related