NSTimer 不工作 Swift

NSTimer not working Swift

我以前见过几次,但我从来没有想过哪里出了问题。

首先,我想创造出像电影中那些黑客场景那样的数字加扰效果。所以,我做了一个 NSTimer 来延迟,这样数字每 0.2 秒就会改变一次。然后,我制作了另一个计时器来告诉我的第一个计时器

invalidate() 

两秒后。我的代码如下:

import UIKit

class MainPage: UIViewController {

@IBOutlet var genericDeviceName: UITextField!
@IBOutlet var hackButton: UIButton!
@IBOutlet var rightNumber: UILabel!
@IBOutlet var leftNumber: UILabel!
@IBOutlet var detectionText: UILabel!

@IBAction func deviceNameEnter(sender: AnyObject) {
    detectionText.text = "Device detected: " + genericDeviceName.text!
    if genericDeviceName.text == "" {
        detectionText.text = "Error"
    }
    hackButton.alpha = 1
}


@IBAction func hackDevice(sender: AnyObject) {
    var tries = 0
    var timer = NSTimer()
    var timerStop = NSTimer()
    timer = NSTimer (timeInterval: 0.2, target: self, selector: "update", userInfo: nil, repeats: true)
    timerStop = NSTimer (timeInterval: 2, target: self, selector: "endTimer", userInfo: nil, repeats: true)

    let diceRoll = Int(arc4random_uniform(9) + 1)
    let diceRollSecond = Int(arc4random_uniform(9) + 1)

    UIView.animateWithDuration(0.25, animations:{
        self.hackButton.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))})

        func update() {leftNumber.text = String(diceRoll)
        rightNumber.text = String(diceRoll)
    print("it worked!")}

    func endTimer() {

    timer.invalidate()
        detectionText.text = "Access Granted!"
        timerStop.invalidate()
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = UIColor.blackColor()
}

所以...出了什么问题?最近几次我尝试使用 NSTimers,它们也没有用。我的 NSTimer 概念错了吗?还是我的代码有错误?没有触发错误消息,只是计时器没有触发,数字也没有改变。甚至 "it worked!" 都没有打印到日志中。请通过建议一些代码来帮助。提前致谢!

更新

我更新了我的代码。这是:

 import UIKit


 class MainPage: UIViewController {



@IBOutlet var genericDeviceName: UITextField!

@IBOutlet var hackButton: UIButton!
@IBOutlet var rightNumber: UILabel!
@IBOutlet var leftNumber: UILabel!
@IBOutlet var detectionText: UILabel!
@IBAction func deviceNameEnter(sender: AnyObject) {



    detectionText.text = "Device detected: " + genericDeviceName.text!

    if genericDeviceName.text == "" {detectionText.text = "Error"}



    hackButton.alpha = 1

}
let diceRoll = Int(arc4random_uniform(9) + 1)
    let diceRollSecond = Int(arc4random_uniform(9) + 1)

func update(timer: NSTimer) {leftNumber.text = String(diceRoll)
    rightNumber.text = String(diceRoll)
    print("it worked!")}

func endTimer(timerStop: NSTimer) {

    timer.invalidate()
    detectionText.text = "Access Granted!"
    timerStop.invalidate()}

@IBAction func hackDevice(sender: AnyObject) {




    var timer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: "update:", userInfo: nil, repeats: true)
    NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
    var timerStop = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "endTimer:", userInfo: nil, repeats: true)
    NSRunLoop.currentRunLoop().addTimer(timerStop, forMode: NSRunLoopCommonModes)


    UIView.animateWithDuration(0.25, animations:{
        self.hackButton.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))})



    }










override func viewDidLoad() {
    super.viewDidLoad()

    self.view.backgroundColor = UIColor.blackColor()


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

 }

目前,由于无法识别变量"timer",函数"endTimer"似乎不​​起作用。请帮忙。非常感谢大家的宝贵时间!

尝试使用这个:

var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "update", userInfo: nil, repeats: true)

同时将 updateendTimer 方法移到 hackDevice 方法之外。

解释:

来自 Apple docs :

Use the timerWithTimeInterval:invocation:repeats: or timerWithTimeInterval:target:selector:userInfo:repeats: class method to create the timer object without scheduling it on a run loop. (After creating it, you must add the timer to a run loop manually by calling the addTimer:forMode: method of the corresponding NSRunLoop object.)

.

Use the scheduledTimerWithTimeInterval:invocation:repeats: or scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: class method to create the timer and schedule it on the current run loop in the default mode.

所以在您的代码中,您只创建了计时器但它没有启动 运行。您必须调用 addTimer(_ timer: NSTimer,forMode mode: String) 来启动计时器,或者您可以简单地使用 scheduledTimerWithTimeInterval 立即启动计时器。

您应该将您的功能移出 hackDevice。 Swift.

一般不会用到像这样的嵌套函数

例如:

let diceRoll = Int(arc4random_uniform(9) + 1)
let diceRollSecond = Int(arc4random_uniform(9) + 1)
var timer = NSTimer()
@IBAction func hackDevice(sender: AnyObject) {

    var tries = 0
    var timer = NSTimer()
    var timerStop = NSTimer()
    timer = NSTimer (timeInterval: 0.2, target: self, selector: "update", userInfo: nil, repeats: true)
    timerStop = NSTimer (timeInterval: 2, target: self, selector: "endTimer", userInfo: nil, repeats: true)



    UIView.animateWithDuration(0.25, animations:{
        self.hackButton.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))})
}

func update() {
    leftNumber.text = String(diceRoll)
    rightNumber.text = String(diceRoll)
    print("it worked!")
}

func endTimer() {
    timer.invalidate()
    detectionText.text = "Access Granted!"
    timerStop.invalidate()
}

一些事情:NSTimer 的选择器应该以冒号结尾(例如 "update:" 或 "endTimer:" 并且该函数应该采用单个参数:NSTimer。

其次,定时器调用的函数必须是目标的顶层函数。您的更新方法是您的 hackDevice 函数的本地函数,该函数不起作用。

第三,需要使用scheduledTimerWithTimeInterval,如ShahiM的回答:

var timer = NSTimer.scheduledTimerWithTimeInterval(
  0.4, 
  target: self, 
  selector: "update:", 
  userInfo: nil, 
  repeats: true)

如果您的选择器中的函数是嵌套函数,则该代码会崩溃,因为它对计时器不可见。

最后,您似乎需要将变量 diceRolldiceRollSecond 移出 hackDevice 函数,并使它们成为 class 的实例变量。

  1. 你不嵌套这种函数,selector不会发现它们,因为它们会在方法退出后暴露出来,函数离开最后一个后}就没有了updateendTiemr
  2. 你的计时器应该是这样的let timer = NSTimer(timeInterval: 0.2, target: self, selector: Selector("update:"), userInfo: nil, repeats: true) 在另一边 func update(timer: NSTimer) {

也可以尝试在初始化后将计时器添加到 运行 循环中:

    let timer = NSTimer(timeInterval: 0.2, target: self, selector: Selector("update:"), userInfo: nil, repeats: true)
    NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)

在你的更新中你重新声明了变量定时器,这样你创建了一个只存在于方法 hackDevice: 中的局部变量,删除 timer = NSTimer.scheduledTimer...

之前的变量

编辑: 我宁愿编辑这个答案,因为在这里我可以添加带有适当换行符和缩进的插入代码片段:

class MainPage: UIViewController{
   // Your IBOutlets
   @IBOutlet var ...
   var timer= NSTimter()

   // Your methods
}