Say you did the following
and proceeded to your business, but the timer fired once or even not a single time. Why? It's because your
timer object has been eaten by garbage collector, and when
DispatchSourceTimer is deinited, it (obviously) stops itself. It's worth reminding that GC is triggered when scope closes, in our case — after
async block fired. Therefore, if you want to regularly run certain task, you should store reference to timer object in a global storage, which would live as long as you want, but not the GC. It's also recommended to wrap access to this storage with synchronous serial queue to avoid shameful race conditions.
P.S. I might be mistaken, but in Swift 3 the behaviour was different, and timer execution did not stop like that. I'm not sure if it's correct behaviour, but anyway, in Swift 4 it's quite reasonable.