美好的一天
我似乎有一个简单的问题,但是我无法解决这个问题。
我在视图控制器内部有一个容器视图。在那个容器里,我几乎没有标签。容器具有自己的视图控制器。在容器的视图控制器中,我正在运行一个计时器,并且我希望该标签显示该计时器。但是每次我使用该标签时,应用都会崩溃 “线程1:致命错误:在展开可选值时意外发现nil”
如果我注释带有此标签的行,则一切运行正常。
@IBOutlet weak var timeLabel: UILabel!
var counter = 0.0
var timer = Timer()
var isRunning = false
func startStopTimer () {
if isRunning {
timer.invalidate()
isRunning = false
}else {
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
isRunning = true
}
}
@objc func updateTimer() {
counter = counter + 0.1
timeLabel.text = String(counter)
}
这是我第一次在主故事板中使用容器视图。
知道我做错了什么或有建议的人可以尝试改变的人吗?
谢谢 乔纳斯(Jonas)
完整代码
class MainViewController: UIViewController {
@IBOutlet weak var topContainer: UIView!
@IBOutlet weak var informationContainer: UIView!
@IBOutlet weak var startStopButtonOutlet: UIButton!
let informationContainerVC = InformationContainerViewController()
override func viewDidLoad() {
super.viewDidLoad()
setupView()
}
func setupView() {
topContainer.layer.cornerRadius = 5
topContainer.layer.masksToBounds = true
informationContainer.layer.cornerRadius = 5
informationContainer.layer.masksToBounds = true
startStopButtonOutlet.layer.cornerRadius = 5
startStopButtonOutlet.layer.masksToBounds = true
}
@IBAction func startStopButton_TouchUpInside(_ sender: UIButton) {
informationContainerVC.startStopTimer()
UIButton.animate(withDuration: 0.1, delay: 0.0, options: [.allowUserInteraction, .curveEaseOut], animations: {
sender.transform = CGAffineTransform.identity
}, completion: nil)
if informationContainerVC.isRunning {
startStopButtonOutlet.setTitle("Push to Pause", for: .normal)
}else {
startStopButtonOutlet.setTitle("Push to Start", for: .normal)
}
}
@IBAction func startStopButton_TouchDown(_ sender: UIButton) {
UIButton.animate(withDuration: 0.1, delay: 0.0, options: [.allowUserInteraction, .curveEaseIn], animations: {
sender.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
if self.informationContainerVC.isRunning {
sender.backgroundColor = UIColor.white.withAlphaComponent(0.5)
}else {
sender.backgroundColor = UIColor.green.withAlphaComponent(0.8)
}
}, completion: nil)
}
@IBAction func startStopButton_TouchUpOutside(_ sender: UIButton) {
UIButton.animate(withDuration: 0.1, delay: 0.0, options: [.allowUserInteraction, .curveEaseOut], animations: {
sender.transform = CGAffineTransform.identity
}, completion: nil)
}
}
这是容器视图控制器的代码
class InformationContainerViewController: UIViewController {
@IBOutlet weak var timeLabel: UILabel!
var counter = 0.0
var timer = Timer()
var isRunning = false
func startStopTimer () {
if isRunning {
timer.invalidate()
isRunning = false
}else {
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
isRunning = true
}
}
@objc func updateTimer() {
counter = counter + 0.1
timeLabel.text = String(counter)
}
}
答案 0 :(得分:0)
说let informationContainerVC = InformationContainerViewController()
时,您正在创建一个InformationContainerViewController
的新实例,该实例未链接到情节提要,因此未设置任何出口。
您需要获得对容器视图中实际存在的视图控制器实例的引用。您可以在prepare(for segue:)
中进行;如果查看情节提要,您会发现有一个嵌入的segue将您的包含视图控制器链接到包含的视图控制器。
在您的MainViewController中:
var informationContainerVC: InformationContainerViewController?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destVC = segue.destination as? InformationContainerViewController {
self.informationContainerVC = destVC
}
}
@IBAction func startStopButton_TouchUpInside(_ sender: UIButton) {
informationContainerVC?.startStopTimer()
UIButton.animate(withDuration: 0.1, delay: 0.0, options: [.allowUserInteraction, .curveEaseOut], animations: {
sender.transform = CGAffineTransform.identity
}, completion: nil)
if informationContainerVC?.isRunning {
startStopButtonOutlet.setTitle("Push to Pause", for: .normal)
} else {
startStopButtonOutlet.setTitle("Push to Start", for: .normal)
}
}
现在您将引用正确的视图控制器实例