簡體   English   中英

快速啟動其他ViewController中的Timer

[英]Start Timer in other viewcontroller in swift

我的計時器功能有問題。 我在單擊btn (startBtn)時啟動一個計時器,並在擊中另一個btn (restBtn)時顯示一個新的viewcontroller作為彈出窗口。現在,它可以正確啟動計時器並以倒計時打開新的viewcontroller作為popover。

問題是,在新的視圖控制器中,它命中0並解散了自己。 它應該在第一個視圖控件中自動啟動計時器。

這是我在mainVC上的代碼:

var timeLeft = 0
var myTimer: Timer!


@IBAction func startBtnPressed(_ sender: AnyObject) {
        timeLeft = 0
        myTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(workoutStartVC.timerRunning), userInfo: nil, repeats: true)  
    }


@IBAction func restBtnPressed(_ sender: AnyObject) {
        print("rest mode button is pressed and i am showing a overlay right now with data count down")
        myTimer.invalidate()

        // show popup when user interacts with restbtn
        let popOpVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "sbPopUpID") as! PopUpVC
        self.addChildViewController(popOpVC)
        popOpVC.view.frame = self.view.frame
        popOpVC.view.backgroundColor = BLUE_COLOR.withAlphaComponent(0.75)
        self.view.addSubview(popOpVC.view)
        popOpVC.didMove(toParentViewController: self)

        timeLbl.text = "" 
    }

func timerRunning() {
        timeLeft = timeLeft + 1
        print("the timeLeft is: \(timeLeft)")

        **timeLbl.text = "\(timeLeft)"** (HERE I AM GETTING ON THE SECOND TIME WHEN DISMISSING THE POPUPVC A FOUND NILL)

        if timeLeft == 30 {
            myTimer.invalidate()
            timeLbl.text = ""
        }
    }

這是我在PopUpVC上的代碼:

var timeLeft = 0
    var myTimer: Timer!

    override func viewDidLoad() {
        super.viewDidLoad()

        timeLeft = 10
        myTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(PopUpVC.timerRunning), userInfo: nil, repeats: true)
    }


    func timerRunning() {
        timeLeft = timeLeft - 1
        restModeTimer.text = "\(timeLeft)"

        if timeLeft == 0 {
            myTimer.invalidate()
            restModeTimer.text = ""
            self.view.removeFromSuperview()

            let worskoutStartVC = workoutStartVC()
            worskoutStartVC.myTimer = nil
            worskoutStartVC.timeLeft = 0

            worskoutStartVC.myTimer = Timer.scheduledTimer(timeInterval: 1.0, target: worskoutStartVC, selector: #selector(worskoutStartVC.timerRunning), userInfo: nil, repeats: true)
        }
    }  

誰能解釋為什么我在下面的代碼中將粗體部分解開選項值時卻得到零?

非常感謝你!

從我所看到的,似乎您正在初始化一行新的View Controller ...:

let worskoutStartVC = workoutStartVC()

因此,當創建此標簽時,標簽的出口連接的方式與從情節提要中初始化視圖時的連接方式不同。

因此,我看到了您可能想嘗試的兩件事:

  1. (可能是最好的選擇)將對原始視圖控制器的引用傳遞給第二個視圖控制器,這樣您就不必再次創建它。 然后使用該引用重新創建計時器。 因為您現在要做的基本上是在每次PopUpVC計時器結束時創建一個新的視圖控制器。 帖子末尾有更多詳細信息

  2. (這將導致初始VC的多個副本,因此它更多地用於幫助理解正在發生的事情)您可以像上面的代碼中一樣使用UIStoryboard()創建視圖控制器的另一個副本,並且應該連接插座正確地。

如您的代碼所述:

// show popup when user interacts with restbtn
    let popOpVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "sbPopUpID") as! PopUpVC
    self.addChildViewController(popOpVC)

同樣,選項1是IMO的最佳選擇,盡管可能還會考慮其他模式。 標簽為nil的原因是,當您使用executionStartVC()創建視圖時,標簽未連接到標簽對象。

編輯 :添加有關如何通過引用的信息:

PopUpVC代碼可能會更改為對原始VC的引用:

var timeLeft = 0
var myTimer: Timer!
var parentVC: workoutStartVC?

override func viewDidLoad() {
    super.viewDidLoad()

    timeLeft = 10
    myTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(PopUpVC.timerRunning), userInfo: nil, repeats: true)
}


func timerRunning() {
    timeLeft = timeLeft - 1
    restModeTimer.text = "\(timeLeft)"

    if timeLeft == 0 {
        myTimer.invalidate()
        restModeTimer.text = ""
        self.view.removeFromSuperview()

        if let worskoutStartVC = workoutStartVC {
            worskoutStartVC.myTimer = nil
            worskoutStartVC.timeLeft = 0

            worskoutStartVC.myTimer = Timer.scheduledTimer(timeInterval: 1.0, target: worskoutStartVC, selector: #selector(worskoutStartVC.timerRunning), userInfo: nil, repeats: true)
        }
    }
}  

過渡到該視圖時,您將必須設置此屬性:(片段)

        // show popup when user interacts with restbtn
        let popOpVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "sbPopUpID") as! PopUpVC
        self.addChildViewController(popOpVC)
        popOpVC.parentVC = self
        popOpVC.view.frame = self.view.frame
        popOpVC.view.backgroundColor = BLUE_COLOR.withAlphaComponent(0.75)
        self.view.addSubview(popOpVC.view)
        popOpVC.didMove(toParentViewController: self)

注意:盡我最大的努力將類名調整為我認為來自您的代碼的類名,但是可能需要進行一些調整。

問題在於, timeLbl可能是一個隱式解包的可選對象,在擁有它的視圖控制器發布后,它意外地為nil。 在關閉彈出窗口時,應通過對其調用invalidate()來使該定時器invalidate() ,以使該定時器回調在不應被觸發后不會被點擊。

此外,由於您已經注意到由於隱式解包的可選而導致的崩潰,因此我建議您要么謹慎處理該計時器回調中的所有情況,以便在不應該調用時調用它,則盡早返回。 (如果確實碰巧存在與計時器相關的錯誤,則至少不會崩潰),或者將當前隱式解包的可選對象改為可選對象,這樣編譯器會告訴您哪些位置易受攻擊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM