2

语境

我是学习 Swift 的初学者,我正在努力确保我理解这个错误“修复”。我跟着一个 Youtube 视频展示了如何在 Xcode 中创建一个计时器。我改变了一些东西以努力学习一些东西,但出现的问题来自原始代码。

错误

每次我启动模拟器时,如果我在没有先启动计时器的情况下按下停止或重置按钮,应用程序将崩溃并在同一行显示此错误timer.invalidate()

在隐式展开可选值时意外发现 nil

我的修复

为了解决我添加的问题?,使其timer?.invalidate()如下面的代码所示。我在谷歌搜索后尝试了这个,以便对正在发生的事情有一个非常松散的了解。

这是否有效,因为计时器尚不存在,因此它是“nil”?

这是防止崩溃的最佳方法吗?似乎我也可以将变量 timer 改为使用?并让它工作,但只有在添加?到 step 函数中的 timer.invalidate() 行以及其他行之后。显然,我需要重新了解我对 Optionals 的理解。

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var label: UILabel!
    
    
    var timeRemaining: Int = 10
    var timer: Timer!
    

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        
    }

    @IBAction func start(_ sender: Any) {
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(step), userInfo: nil, repeats: true)
        
    }
    
    @IBAction func stop(_ sender: Any) {
        timer?.invalidate() //added ? to timer
    }
    
    @IBAction func reset(_ sender: Any) {
        timer?.invalidate() //added ? to timer
        timeRemaining = 10
        label.text = "\(timeRemaining)"
    }
    
    @objc func step() {
        if timeRemaining > 0 {
            timeRemaining -= 1
        } else {
            timer.invalidate()
        }
        label.text = "\(timeRemaining)"
    }
    

}
4

2 回答 2

1

不要将您的计时器声明为隐式展开的可选项。改变

var timer: Timer! 

weak var timer: Timer?

(用问号代替感叹号。)

然后是的,将您的代码更改为阅读timer?.invalidate()

编辑:

请注意,您的按钮代码也应该使计时器无效:

@IBAction func start(_ sender: Any) {
    timer?.invalidate()
    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(step), userInfo: nil, repeats: true)        
}

如果您在创建新计时器之前没有使计时器无效,则您可以同时运行计时器的多个实例,并且当您将变量中的一个替换timer为新的时,您无法访问前一个再阻止它。

于 2021-05-01T18:28:23.237 回答
1
var timer: Timer!

意味着你告诉编译器你确定永远不会timernil所以如果你尝试使用变量并且它是 nil 你会崩溃。这可能是发生在您身上的事情:reset(_:)调用.stop(_:)start(_:)

timer?.invalidate() //added ? to timer

修复崩溃,因为现在您正在timer通过可选链接访问。

但它并没有解决无处不在的潜在问题,因此声明:

var timer: Timer?

更安全

于 2021-05-01T18:58:20.510 回答