#1 -
Currently, DispatchQueue.after() takes an absolute time as the “after”
parameter. This makes it hard to understand how to use it; you need to go
digging through generated interfaces to find out what a ‘DispatchTime’ is and
how you construct it (by getting the .now() and adding a DispatchTimeInterval
using one of the easily-missable operator overloads, if you were wondering).
Here is what DispatchQueue.after looks like now:
public func after(when: DispatchTime, qos: DispatchQoS = .unspecified, flags:
DispatchWorkItemFlags = [], execute work: @convention(block) () -> Void)
So to use it, you have to type:
DispatchQueue.main.after(when: DispatchTime.now() + .milliseconds(250)) { /*
do stuff */ }
I don’t believe this is a great fit with the Swift API Guidelines. I believe
the name “after” already implies that the time is relative, the argument label
should be dropped, and that nuances about the clock (basically, whether or not
it pauses during system sleep) are edge-cases which can be handled for the
majority of users with a sensible default value (or better yet, modelling via
an enum or boolean switch — see #2). Additionally, There are overloads with
“wallTime” parameter labels which seem only to duplicate type information (the
monotonic and walltime clocks are actually split at the type level) and could
be more concise and readable. The principle is that, ultimately, you should
just be able to write the above code like this:
DispatchQueue.main.after(.milliseconds(250)) { /* do stuff */ }
Or
DispatchQueue.main.at(DispatchTime.now() + .seconds(3)) { /* do stuff */ }
It’s not something you use all the time (like .sync/.async), but I find that
whenever I do need it I’m frustrated by how needlessly complex it is to
decipher and use. I would find these methods much more obvious, I could figure
out how to use them much more quickly, and I think I’d remember how to use them
more quickly.
—
#2 -
Actually, while writing this down it’s becoming clearer and clearer that the
idea to split DispatchTime (the monotonic clock) and DispatchWallTime (the wall
clock) at the type level is probably a bad idea.
Novice users are not going to understand what’s going on here - I expect most
of them to default to the more generic-sounding “DispatchTime” without any idea
of the implications of this. Perhaps we should look at replacing these clock
variations with a more descriptive enum or boolean, rather than a separate
type. For example:
struct DispatchTime { // replaces DispatchTime and
DispatchWallTime
let rawValue : dispatch_time_t
let clock : Clock
enum Clock { case monotonicClock; case wallClock }
}
This would not obsolete the discussion at the start about “after”. The name
“after” still implies that I want something done at some duration relative to
an absolute point in time (usually now).
Thoughts?
There have been some really in-depth naming discussions on here recently, so
I’m interested to hear what you make of it.
Karl
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution