我现在有这个问题几天了,我不知道我做错了什么。
我的应用程序基本上只是创建一些计时器。我需要阻止他们并创造新的。但目前阻止它们是行不通的。
self.timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target:self, selector: "timerDidEnd:", userInfo: "Notification fired", repeats: false)
这是我的计时器
func timerDidEnd(timer:NSTimer){
createUnrepeatedAlarmWithUpdateInterval()
}
因为我的计时器不想停止我正在使用未重复的计时器并在它停止后自己启动它。
func stopAlarm() {
if self.timer != nil {
self.timer!.invalidate()
}
self.timer = nil
self.timer = NSTimer()
}
这就是我停止计时器的方式。
alarmManager.stopAlarm()
alarmManager.createUnrepeatedAlarmWithUpdateInterval()
我在创建新计时器之前调用stopAlarm()
函数。
我真的不知道我做错了什么,所以我很感激每一个答案:)
class AlarmManager: ViewController{
private var timer : NSTimer?
private var unrepeatedTimer : NSTimer?
private let notificationManager = NotificationManager()
private var current = NSThread()
private let settingsViewController = SettingsViewController()
func createRepeatedAlarmWithUpdateInterval(){
var timeInterval:NSTimeInterval = settingsViewController.getUpdateIntervalSettings()
if timer == nil{
timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval,
target: self,
selector: "repeatedTimerDidEnd:",
userInfo: "Notification fired",
repeats: true)
}
}
func repeatedTimerDidEnd(repeatedTimer:NSTimer){
ConnectionManager.sharedInstance.loadTrainings(settingsViewController.getServerSettings())
createUnrepeatedAlarm(10)
}
func createUnrepeatedAlarm(timeInterval:Double){
unrepeatedTimer = NSTimer.scheduledTimerWithTimeInterval(timeInterval,
target: self,
selector: "unrepeatedTimerDidEnd:",
userInfo: "Notification fired",
repeats: false)
}
func unrepeatedTimerDidEnd(unrepeatedTimer:NSTimer){
notificationManager.createNotification(self, reminderType: NotificationManager.ITEMRATINGREMINDER)
notificationManager.createNotification(self, reminderType: NotificationManager.ITEMREMINDER)
print("UnrepeatedAlarm ended")
}
func stopAlarm(){
print("StopAlarm triggered")
if (timer != nil)
{
print("stoptimer executed")
timer!.invalidate()
timer = nil
}
if (unrepeatedTimer != nil)
{
unrepeatedTimer!.invalidate()
unrepeatedTimer = nil
}
}
}
这个类的全部代码。也许这有帮助:D
答案 0 :(得分:29)
安全启动和停止计时器的常用方法是
var timer : NSTimer?
func startTimer()
{
if timer == nil {
timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: "timerFired", userInfo: nil, repeats: true)
}
}
func stopTimer()
{
if timer != nil {
timer!.invalidate()
timer = nil
}
}
startTimer()
仅在nil
和stopTimer()
仅在不是nil
时停止计时器时启动计时器。
在创建/开始新计时之前,您只需要停止计时器。
在 Swift 3 替换
NSTimer
与Timer
,NSTimer.scheduledTimerWithTimeInterval(
与Timer.scheduledTimer(timeInterval:
selector: "timerFired"
与selector: #selector(timerFired)
。答案 1 :(得分:5)
确保在与计时器相同的线程上调用无效。
从文档中:
特殊注意事项 您必须从安装计时器的线程发送此消息。如果从另一个线程发送此消息,则与计时器关联的输入源可能不会从其运行循环中删除,这可能会阻止线程正常退出。
https://developer.apple.com/documentation/foundation/nstimer/1415405-invalidate?language=objc
答案 2 :(得分:0)
以前的答案未真正涵盖的某件事是,您应注意不要将计时器安排多次。
如果您多次调度计时器而没有首先使它无效,则它将最终安排在多个运行循环中,并且使它无效几乎就不可能了。
对我来说,在视图控制器生命周期(scheduleTimer()
,viewWillAppear
,...)的单独函数中调用viewDidAppear
函数时发生了
因此,简而言之,如果您不确定(或不能保证)您的计时器仅安排一次,请始终先使其无效。
答案 3 :(得分:0)
我已经尝试了找到的所有可能的解决方案,但最终无法解决这个问题,我在初始化如下定时器时设置了重复“假”
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(viewcontroller.methodname), userInfo: nil, repeats: false)
并且需要在我的选择器方法中添加以上行,以用于我想要重复时间的任何条件。
例如:- 我的要求是我想重复调用某个方法直到满足一个条件。因此,我没有添加重复 true,而是将其设置为 false,因为在我的情况下,repeat true 不会使计时器失效。
我在我的 viewdidload 方法中添加了以下内容
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(viewcontroller.method), userInfo: nil, repeats: false)
在选择器函数中我添加了下面的代码
@objc func 方法{
if condition not matched{
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(viewcontroller.method), userInfo: nil, repeats: false)
}
else{
// once you are here your timer invalidate automatically
}
}
希望这能解决您的问题
答案 4 :(得分:0)
对于 Swift 5 Xcode 12.4,有使用计时器的示例:
class MyController: UIViewController {
private id: Float;
func setValue(_ value: Float, withAnimation: Bool) {
let step: Float = value / 200
var current: Float = withAnimation ? 0.0 : value
let _ = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: withAnimation) { timer in
DispatchQueue.main.async {
self.id = current
current += step
if current > value || withAnimation == false {
self.id = current
timer.invalidate()
}
}
}
}
}