swift 无效计时器不起作用
swift invalidate timer doesn't work
我已经有几天遇到这个问题了,但我不明白自己做错了什么。
我的应用程序基本上只是在创建一些计时器。我需要阻止它们并创建新的。但是目前停止他们是行不通的。
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
}
}
}
这就是 class 的全部代码。也许这有帮助 :D
安全启动和停止计时器的常用方法是
var timer : Timer?
func startTimer()
{
if timer == nil {
timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)
}
}
func stopTimer()
{
if timer != nil {
timer!.invalidate()
timer = nil
}
}
startTimer()
仅在 nil
时启动计时器,而 stopTimer()
仅在不是 nil
时停止计时器。
你只需要在creating/starting一个新的计时器之前注意停止计时器。
确保您在与计时器相同的线程上调用 invalidate。
来自文档:
Special Considerations
You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.
https://developer.apple.com/documentation/foundation/nstimer/1415405-invalidate?language=objc
之前的答案没有真正涵盖的是,您应该小心您的计时器没有被安排多次。
如果您多次安排一个计时器而不首先使它无效,它将最终安排在多个 运行 循环中,然后使它无效几乎是不可能的。
对我来说,它发生在我的视图控制器生命周期中的单独函数中调用我的 scheduleTimer()
函数时(viewWillAppear
、viewDidAppear
、...)
简而言之,如果您不确定(或不能保证)您的定时器只被调度一次,那么总是先使其无效。
我已经尝试了所有可能的解决方案,但无法解决,最后我在初始化计时器时设置了重复“false”,如下所示
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(viewcontroller.methodname), userInfo: nil, repeats: false)
并且需要在我的选择器方法中添加上面一行,无论我想重复时间的条件是什么。
例如:-
我的要求是我想重复调用一些方法直到满足一个条件。因此,我没有添加 repeats true,而是将其设置为 false,因为在我的情况下,repeat true 不会使计时器无效。
我在我的 viewdidload 方法中添加了以下内容
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(viewcontroller.method), userInfo: nil, repeats: false)
在选择器函数中我添加了下面的代码
@objc 函数方法{
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
}
}
希望这能解决您的问题
对于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()
}
}
}
}
}
我已经有几天遇到这个问题了,但我不明白自己做错了什么。
我的应用程序基本上只是在创建一些计时器。我需要阻止它们并创建新的。但是目前停止他们是行不通的。
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
}
}
}
这就是 class 的全部代码。也许这有帮助 :D
安全启动和停止计时器的常用方法是
var timer : Timer?
func startTimer()
{
if timer == nil {
timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)
}
}
func stopTimer()
{
if timer != nil {
timer!.invalidate()
timer = nil
}
}
startTimer()
仅在 nil
时启动计时器,而 stopTimer()
仅在不是 nil
时停止计时器。
你只需要在creating/starting一个新的计时器之前注意停止计时器。
确保您在与计时器相同的线程上调用 invalidate。
来自文档:
Special Considerations You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.
https://developer.apple.com/documentation/foundation/nstimer/1415405-invalidate?language=objc
之前的答案没有真正涵盖的是,您应该小心您的计时器没有被安排多次。
如果您多次安排一个计时器而不首先使它无效,它将最终安排在多个 运行 循环中,然后使它无效几乎是不可能的。
对我来说,它发生在我的视图控制器生命周期中的单独函数中调用我的 scheduleTimer()
函数时(viewWillAppear
、viewDidAppear
、...)
简而言之,如果您不确定(或不能保证)您的定时器只被调度一次,那么总是先使其无效。
我已经尝试了所有可能的解决方案,但无法解决,最后我在初始化计时器时设置了重复“false”,如下所示
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(viewcontroller.methodname), userInfo: nil, repeats: false)
并且需要在我的选择器方法中添加上面一行,无论我想重复时间的条件是什么。
例如:- 我的要求是我想重复调用一些方法直到满足一个条件。因此,我没有添加 repeats true,而是将其设置为 false,因为在我的情况下,repeat true 不会使计时器无效。
我在我的 viewdidload 方法中添加了以下内容
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(viewcontroller.method), userInfo: nil, repeats: false)
在选择器函数中我添加了下面的代码
@objc 函数方法{
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
}
}
希望这能解决您的问题
对于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()
}
}
}
}
}