How do I fix this code so it doesn't give the error: Type of expression is ambiguous without more context?
var int = 0
while int < 100 {
DispatchQueue.main.asyncAfter(deadline: .now() + int) { // change 2 to desired number of seconds
// do stuff
}
int += 1
}
The code is being run in dispatch queue in applicationDidEnterBackground, in an attempt to make text to speech work in the background.
The Type of expression is ambiguous without more context error is stemming from two facts:
DispatchTime
and an Int
..now()
.Swift doesn't know how to add a DispatchTime
and an Int
This can be demonstrated with:
let t = DispatchTime.now() + Int(5)
Binary operator '+' cannot be applied to operands of type 'DispatchTime' and 'Int'
but Swift does know how to add a DispatchTime
and a Double
:
let t = DispatchTime.now() + Double(5)
This compiles fine with no errors.
So why does
DispatchQueue.main.asyncAfter(deadline: .now() + 5)
work?
In this case, Swift is interpreting the integer literal 5
as a Double
. Type Double
conforms to the protocol ExpressibleByIntegerLiteral
which is what allows you to do:
let d: Double = 5
So in this case, it works because 5
isn't an Int
, it's a Double
.
Because of fact 1, Swift doesn't know how to interpret .now()
When you tried to add an Int
to .now()
:
DispatchQueue.main.asyncAfter(deadline: .now() + int)
the Swift type inference system got confused. Swift knows that it wants to pass a DispatchTime
to asyncAfter(deadline:)
, but it no longer could figure out what .now()
is because there is no way to add a DispatchTime
and an Int
to get a DispatchTime
, it decided that .now()
was not a DispatchTime
but some other unknown type. So the ambiguous error message is coming from Swift's inability to determine what .now()
is.
If you make that explicit by saying DispatchTime.now()
, then you get a more sensible error:
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + int)
Binary operator '+' cannot be applied to operands of type 'DispatchTime' and 'Int'
As further evidence of this theory, if you provide Swift a way to add a DispatchTime
and an Int
, Swift is happy with your original code:
func +(_ lhs: DispatchTime, _ rhs: Int) -> DispatchTime {
return lhs + .seconds(rhs)
}
So what is this
.seconds()
stuff? And how does it help solve the error?
There is a related enum
type DispatchTimeInterval
that has cases microseconds(Int)
, milliseconds(Int)
, nanoseconds(Int)
, seconds(Int)
and never
. Swift knows how to add a DispatchTime
and a DispatchTimeInterval
, so Swift is able to interpret .seconds(int)
as a DispatchTimeInterval
which then allows it to interpret .now()
as a DispatchTime
.
Why did the Swift designers choose to let you add a
Double
to aDispatchTime
and not anInt
?
You'd have to ask them. I suspect they chose the Double
out of convenience (allowing literal values such as 2.5
to be used) and because it allows you to specify time intervals smaller than one second. The Int
doesn't give you any extra capabilities (except of course for eliminating this very confusing error message).
Conclusion
The error is coming from the fact that you confused Swift's type inference system by trying to add an Int
to a DispatchTime
.
The fixes as the other answers suggested:
Use a Double
.
or
Use the DispatchTimeInterval
enum
to explicitly note what your Int
represents. In your case .seconds(int)
.