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)
同时将 update
和 endTimer
方法移到 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)
如果您的选择器中的函数是嵌套函数,则该代码会崩溃,因为它对计时器不可见。
最后,您似乎需要将变量 diceRoll
和 diceRollSecond
移出 hackDevice
函数,并使它们成为 class 的实例变量。
- 你不嵌套这种函数,
selector
不会发现它们,因为它们会在方法退出后暴露出来,函数离开最后一个后}
就没有了update
和 endTiemr
- 你的计时器应该是这样的
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
}
我以前见过几次,但我从来没有想过哪里出了问题。
首先,我想创造出像电影中那些黑客场景那样的数字加扰效果。所以,我做了一个 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)
同时将 update
和 endTimer
方法移到 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)
如果您的选择器中的函数是嵌套函数,则该代码会崩溃,因为它对计时器不可见。
最后,您似乎需要将变量 diceRoll
和 diceRollSecond
移出 hackDevice
函数,并使它们成为 class 的实例变量。
- 你不嵌套这种函数,
selector
不会发现它们,因为它们会在方法退出后暴露出来,函数离开最后一个后}
就没有了update
和endTiemr
- 你的计时器应该是这样的
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
}