SwiftyTimer icon indicating copy to clipboard operation
SwiftyTimer copied to clipboard

Crash when calling fire() after creating timer

Open BenchR267 opened this issue 7 years ago • 10 comments

The following code worked with 1.3.0 but crashes with 1.4.0:

let timer = NSTimer.every(1) { 
            print("do something!")
        }
timer.fire()

The internal refactoring of not using NSTimer initializers might be the problem.

BenchR267 avatar Jul 22 '16 09:07 BenchR267

could you give more info? OS version, crash log?

radex avatar Jul 22 '16 13:07 radex

Crashed: com.apple.main-thread EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000043000002

Crashed: com.apple.main-thread 0 libobjc.A.dylib 0x19860dbc8 objc_msgSend + 8 1 CoreFoundation 0x1839f3580 -[__NSCFTimer fire] + 120

This is happening on every device, every OS I tried (iOS, iPhone)

BenchR267 avatar Jul 22 '16 14:07 BenchR267

Looks like the CFTimer → NSTimer bridging is lacking, and a bridged timer doesn't actually have a fire() method...

screen shot 2016-07-23 at 08 43 13

It is an edge case, but still worth reverting to the old method of initializing timers...

@BenchR267 Would you mind filing the bug with Apple (bugreport.apple.com), so that it's also fixed for everyone?

radex avatar Jul 23 '16 06:07 radex

Oh yeah, sorry, forgot to answer. I'll create a bugticket at Apple.

BenchR267 avatar Aug 05 '16 09:08 BenchR267

@radex Will you revert to the old way anytime soon? Asking because you said you would, but there have been no changes to that.

maxkattner avatar Aug 08 '16 09:08 maxkattner

I intend to… The trouble is that if I do that, I lose compatibility with SwiftPM (old method requires ObjC runtime)... Perhaps a conditional implementation (Using either CFRunLoopTimer API or the new block-based API) would do the job. PRs welcome.

radex avatar Aug 08 '16 11:08 radex

Is there a workaround for this? Its crashing my app as well.

scisci avatar Oct 02 '16 16:10 scisci

@scisci we are using an older version of SwiftyTimer which doesn't have the issues.

BenchR267 avatar Oct 07 '16 08:10 BenchR267

I also encountered this issue, The context is if the user is about to switch views that if a certain timer that calls a function to hide certain messages has not done so when its about to switch, it fires then invalidates the timer.

So instead of fire() i set the fireDate to now and then have a completion block for any code that needs to happen after the timer has fired (e.g invalidating after firing). If the code after the call is not dependant on the timer firing it does not need to be in the block.

typealias VanillaClosure = () -> Void
@objc(fireNowThen:)
func fire(completionBlock: VanillaClosure?) {
    fireDate = Date()
    MTq.after(0.1) {
        completionBlock?()
    }
}

MTq is a legacy obj-c library, which is just syntax sugar for GCD that could easily be GCD or any other GCD-esque library

Genhain avatar Nov 23 '17 04:11 Genhain

This just got me as well, a bummer! Luckily in this project I targeted iOS 10, which does have a Timer API that is closer to SwiftyTimer in simplicity and elegance.

rafaelnobrepd avatar Dec 22 '17 20:12 rafaelnobrepd