J. Doe
J. Doe

Reputation: 551

NSTimer invalidation does not work properly

I'm using NSTimer in my project:

var clickTimer: Timer?

override func mouseDown(with event: NSEvent) {
    clickTimer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(close(timer:)), userInfo: nil, repeats: false)
}

and later I invalidate it in

override func mouseUp(with event: NSEvent) {
    if let timer = self.clickTimer {
        timer.invalidate()
    }
}

the code inside of mouseUp is running but the close method of the timer is still running in 2 seconds. Why invalidation does not work?

Upvotes: 1

Views: 67

Answers (6)

akira
akira

Reputation: 1

try this -

if (self.clickTimer == nil) { 
self.clickTimer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(close(timer:)), userInfo: nil, repeats: false) 
}

Upvotes: 0

iShox
iShox

Reputation: 369

Try this

private var clickTimer: NSTimer?

func functionname() {
        guard clickTimer == nil else { return }
        clickTimer = NSTimer.scheduledTimerWithTimeInterval(15, target: self, selector: "fetchWallPosts", userInfo: nil, repeats: true)
    }

or

self. clickTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(yourmethod)), userInfo: nil, repeats: true)

Upvotes: 0

Oliver Atkinson
Oliver Atkinson

Reputation: 8029

The problem arises when mouseDown(with:) is called multiple times, your original timer will be replaced which therefore means you have no reference to invalidate it.

var clickTimer: Timer?

override func mouseDown(with event: NSEvent) {
    clickTimer?.invalidate()
    clickTimer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(close(timer:)), userInfo: nil, repeats: false)
}

override func mouseUp(with event: NSEvent) {
    clickTimer?.invalidate()
}

Upvotes: 0

Mohammad Reza Koohkan
Mohammad Reza Koohkan

Reputation: 1734

you are invalidate an instance of self.clickTimer , you should invalidate self.clickTimer

override func mouseUp(with event: NSEvent) {
  if let timer = self.clickTimer {
      self.clickTimer.invalidate()
  }
}

Update

i see , you didnt fire the clickTimer ! first if you want to do like this you must fire this variable -> clickTimer.fire()

then when you wanted you should invalidate ,

'Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(close(timer:)), userInfo: nil, repeats: false)

automatic runs when you want to declare clickTimer but its not what you want to invalidate !!!

Upvotes: 0

0yeoj
0yeoj

Reputation: 4550

I see now., You dont want to redeclare your clickTimer so what you want to do is

if (self.clickTimer == nil) { 
    self.clickTimer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(close(timer:)), userInfo: nil, repeats: false) 
}


Just a thought though, you are reinitializing the clicktimer multiple times, the previous was successfully invalidated but you accidentally redeclaring a new timer.. hmm..

I also suggest you add self.clickTimer = nil after timer.invalidate() just to be safe

Upvotes: 2

J. Doe
J. Doe

Reputation: 13033

Try this code, invalidate it first and than remove the reference.

override func mouseUp(with event: NSEvent) {
    self.clickTimer?.invalidate()
    self.clickTimer = nil
}

Upvotes: 0

Related Questions