I'd like to schedule jobs, and pass a completion handler to each job like so:
class Scheduler {
var jobs = [(() -> ()) -> ()]()
func schedule(block: @escaping (() -> ()) -> ()) {
jobs.append(block)
}
func run() {
if !jobs.isEmpty {
let job = jobs.removeFirst()
// Run the next job when this job is done
job { self.run() }
}
}
}
func test() {
let s = Scheduler()
s.schedule { next in
// Perform some work, this requires `next` to be escaping:
DispatchQueue.main.async(execute: next)
}
// later
s.run()
}
The swift compiler does not like that next is escaping, without being marked as such:
main.swift:22:43: error: passing non-escaping parameter 'next' to function expecting an @escaping closure
DispatchQueue.main.async(execute: next)
^
main.swift:21:28: note: parameter 'next' is implicitly non-escaping
Scheduler().schedule { next in
^
The obvious change would be to mark the next argument as escaping:
func schedule(block: @escaping (@escaping () -> ()) -> ()) {
But now the compiler seems to be mistakenly mark the block as non-escaping:
main.swift:9:21: error: using non-escaping parameter 'block' in a context expecting an @escaping closure
jobs.append(block)
^
main.swift:8:19: note: parameter 'block' is implicitly non-escaping
func schedule(block: @escaping (@escaping () -> ()) -> ()) {
^
@escaping
Is this a known compiler issue? Are there workarounds?