2

如何修复此代码,使其不会给出错误:没有更多上下文的表达式类型不明确?

var int = 0
while int < 100 {
        DispatchQueue.main.asyncAfter(deadline: .now() + int) { // change 2 to desired number of seconds
            // do stuff
        }
        int += 1
}

该代码正在 applicationDidEnterBackground 的调度队列中运行,以尝试使文本到语音在后台工作。

4

3 回答 3

8

表达式的类型是模棱两可的,没有更多的上下文错误源于两个事实:

  1. Swift 不知道如何添加 aDispatchTimeInt.
  2. 由于事实 1,Swift 不知道如何解释.now().

Swift 不知道如何添加 aDispatchTime和 anInt

这可以通过以下方式证明:

let t = DispatchTime.now() + Int(5)

二元运算符“+”不能应用于“DispatchTime”和“Int”类型的操作数

但 Swift 确实知道如何添加 aDispatchTime和 a Double

let t = DispatchTime.now() + Double(5)

这编译得很好,没有错误。

那么为什么DispatchQueue.main.asyncAfter(deadline: .now() + 5)有效呢?

在这种情况下,Swift 将整数文字解释5Double. 类型Double符合ExpressibleByIntegerLiteral允许您执行的协议:

let d: Double = 5

所以在这种情况下,它可以工作,因为5它不是一个Int,而是一个Double

由于事实 1,Swift 不知道如何解释.now()

当您尝试添加Intto 时.now()

DispatchQueue.main.asyncAfter(deadline: .now() + int)

Swift 类型推理系统很困惑。Swift 知道它想将 a 传递DispatchTimeasyncAfter(deadline:),但它不再能够弄清楚是什么.now(),因为无法添加 aDispatchTime和 anInt来获得 a DispatchTime,它决定那.now()不是 aDispatchTime而是其他一些未知类型。因此,模棱两可的错误消息来自 Swift 无法确定是什么.now()

如果你通过说 来明确表示DispatchTime.now(),那么你会得到一个更明智的错误:

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + int)

二元运算符“+”不能应用于“DispatchTime”和“Int”类型的操作数

作为该理论的进一步证据,如果您为 Swift 提供一种添加 aDispatchTime和 an 的方法Int,Swift 会对您的原始代码感到满意:

func +(_ lhs: DispatchTime, _ rhs: Int) -> DispatchTime {
    return lhs + .seconds(rhs)
}

那么这是什么.seconds()东西呢?它如何帮助解决错误?

有一个相关类型enumDispatchTimeIntervalcase microseconds(Int)milliseconds(Int)nanoseconds(Int)和。Swift 知道如何添加 a和 a ,因此 Swift 能够解释为 a which 然后允许它解释为 a 。seconds(Int)neverDispatchTimeDispatchTimeInterval.seconds(int)DispatchTimeInterval.now()DispatchTime

为什么 Swift 设计者选择让你添加 aDouble到 aDispatchTime而不是 a Int

你得问他们。我怀疑他们Double出于方便而选择了(允许使用诸如文字值之类的值2.5),并且因为它允许您指定小于一秒的时间间隔。Int不会为您提供任何额外的功能(当然除了消除这个非常令人困惑的错误消息)。

结论

错误来自您尝试将 Swift 添加IntDispatchTime.

其他答案建议的修复:

  1. 使用Double.

    或者

  2. 使用DispatchTimeInterval enum来明确注意您所Int代表的内容。在你的情况下.seconds(int)

于 2018-08-27T10:45:36.780 回答
4

您需要使用变量添加到.now().

var delay: Double = 0
while delay < 100 {
        DispatchQueue.main.asyncAfter(deadline: .now() + delay) { // change 2 to desired number of seconds
            // do stuff
        }
        int += 1
}
于 2018-08-27T07:18:28.787 回答
2

你可以DispatchTime用文字做数学

DispatchQueue.main.asyncAfter(deadline: .now() + 2)

但不是Int变量,这就是歧义。有一个DispatchTimeInterval枚举可以传递一个Int变量

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(int))
于 2018-08-27T08:08:17.593 回答