Swift 应用程序在计时器后崩溃,而不是重新启用按钮

Swift 应用程序在计时器后崩溃,而不是重新启用按钮,swift,xcode,uibutton,nstimer,Swift,Xcode,Uibutton,Nstimer,我是XCode新手,因此任何帮助都将不胜感激 按下按钮时,按钮应被禁用,并应显示随机数并触发计时器。定时器完成后,按钮再次启用 以下是按钮代码: @IBAction func MarketButton(_ sender: UIButton) { let t = Int(arc4random_uniform(10)) MarketLabel.text = String (t) let timer = Timer.scheduledTimer(timeInterval: 10

我是XCode新手,因此任何帮助都将不胜感激

按下按钮时,按钮应被禁用,并应显示随机数并触发计时器。定时器完成后,按钮再次启用

以下是按钮代码:

@IBAction func MarketButton(_ sender: UIButton) {
    let t = Int(arc4random_uniform(10))
    MarketLabel.text = String (t)
    let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(MarketViewController.MarketButton), userInfo: nil, repeats: false)
    sender.isEnabled = !(timer.isValid )

这里有几个问题:

导致崩溃的原因是
MarketButton
要求您传入UIButton作为参数,而定时器在触发时没有这样做。您可以通过
scheduledTimer
的userInfo参数传入按钮来完成此操作。下面是一篇关于如何做堆栈溢出的帖子

然而,即使在你做了这些事情之后,这些事情仍然不起作用。 您需要创建一个方法来处理计时器何时完成

比如:

func enableButton() {
    yourButton.isEnabled = true
}
然后将其作为选择器,而不是
MarketButton
方法

像这样:

let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(enableButton), userInfo: nil, repeats: false)
通过将“MarketButton”作为计时器的选择器,您将导致一个无限循环。当计时器完成时,它调用方法,然后触发另一个计时器,依此类推

另一个问题是这两行代码:

let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(MarketViewController.MarketButton), userInfo: nil, repeats: false)
sender.isEnabled = !(timer.isValid )
在这种情况下,计时器几乎总是有效的,因为您只需设置它。所以
!(timer.isValid)
基本上总是返回false。但是,如果您按照我的建议触发另一种方法,而不是
MarketButton
,那么这将不会是一个问题

还有一个补充说明,在命名函数时,不应将它们大写,因此
MarketButton
应为
MarketButton


我建议尝试用我给你的信息来找到解决方案。如果您有任何问题,请告诉我,欢迎来到stack overflow

欢迎使用堆栈溢出。让我带您了解一下按下按钮后代码正在执行的操作

  • 创建一个介于0和10之间的随机数
  • 把号码放在标签上
  • 安排计时器以启动相同的功能
  • 如果计时器有效,它将禁用该按钮。如果计时器无效,它将启用按钮
  • 但是,在计时器触发后,它调用相同的函数。不过这次它不会有相同的参数。在第一次运行中,按钮将自己传递给函数a,并传递第一个参数。这一次,计时器将是第一个参数。不幸的是,选择器API不是类型安全的。下面是计时器一触发就会发生的情况:

  • 函数被调用
  • 将生成一个随机数并写入标签
  • 新计时器启动
  • 运行iOS应用程序的objective C运行时试图查找并
    isEnabled
    属性,但它在计时器上找不到该属性,因此会崩溃 因此,计时器调用另一个函数(如@boidkan)是至关重要的。我建议这样做:

    class TimebombViewController {
        @IBOutlet weak var timerLabel: UILabel!
        @IBOutlet weak var startButton: UIButton!
    
        var timer: Timer?
        @IBAction startButtonPressed(_ sender:UIButton){
            timerLabel.text = Int(arc4random_uniform(10)).description
            timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(timerFired), userInfo: nil, repeats: false)
            refreshButtonState()
        }
    
        @objc timerFired(_ timer:Timer){
            timer = nil
            refreshButtonState()
        }
    
        func refreshButtonState(){
            startButton.isEnabled = !(timer?.isValid ?? false)
        }
    
    }
    

    欢迎来到Stackoverflow!请包括您得到的错误、输出或行为。线程1:信号SIGABRTI认为这件事崩溃的最重要原因是计时器正在调用选择器MarketButton:这要求按钮作为其第一个也是唯一的参数。您的任何其他备注仍然适用,但它应该失败,因为计时器不是UIButton类型,这就是为什么它无法检查该对象上的isEnabled属性。嗯,您想发布解决方案吗?需要多个答案:我想你可以在你的答案中加上我的评论。否则,我将重新发布您的大部分原始答案;-)谢谢你们两位,@boidkan感谢你们的帮助和问候,不幸的是,我对代码仍然有一点问题。计时器似乎不工作,按钮也没有禁用。var timer:timer?iButton:UIButton!iAction func marketButton(uSender:UIButton){marketLabel.text=Int(arc4random_uniform(10)).description timer=timer.scheduledTimer(时间间隔:10,目标:self,选择器:#选择器(enableButton),userInfo:nil,repeats:false)}objc func enableButton(){timer=nil marketButtons.isEnabled=!(计时器?.isValid?false)