表达式类型不明确,没有更多上下文错误

时间:2018-08-27 07:14:23

标签: ios swift xcode dispatch-queue

我该如何修复此代码,以免出现错误:表达式类型不明确且没有更多上下文?

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

该代码正在applicationDidEnterBackground的分派队列中运行,试图使文本到语音在后台工作。

3 个答案:

答案 0 :(得分:3)

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

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

Swift不知道如何添加DispatchTimeInt

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

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

二进制运算符'+'不能应用于类型'DispatchTime'和'Int'的操作数

但是Swift确实知道如何添加DispatchTimeDouble

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

这可以正常编译,没有错误。

  

那么DispatchQueue.main.asyncAfter(deadline: .now() + 5)为什么起作用?

在这种情况下,Swift将整数文字5解释为Double。类型Double符合协议ExpressibleByIntegerLiteral,该协议允许您执行以下操作:

let d: Double = 5

因此在这种情况下,它是有效的,因为5不是Int,而是Double

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

当您尝试将Int添加到.now()时:

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

Swift类型推断系统感到困惑。 Swift知道它想将DispatchTime传递给asyncAfter(deadline:),但是由于无法添加.now()和{ {1}}得到DispatchTime,它决定Int不是DispatchTime而是其他未知类型。因此,模棱两可的错误消息来自Swift无法确定.now()是什么。

如果您通过说DispatchTime来使之明确,那么您将得到一个更明智的错误:

.now()
  

二进制运算符'+'不能应用于类型'DispatchTime'和'Int'的操作数

作为该理论的进一步证据,如果您为Swift提供一种添加DispatchTime.now()DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + int) 的方法,那么Swift会对您的原始代码感到满意:

DispatchTime
  

那么Int这是什么东西?以及如何帮助解决错误?

有一个相关的func +(_ lhs: DispatchTime, _ rhs: Int) -> DispatchTime { return lhs + .seconds(rhs) } 类型.seconds(),具有案例enumDispatchTimeIntervalmicroseconds(Int)milliseconds(Int)nanoseconds(Int) 。 Swift知道如何添加seconds(Int)never,因此Swift可以将DispatchTime解释为DispatchTimeInterval,然后允许将.seconds(int)解释为DispatchTimeInterval

  

Swift设计师为什么选择让您在.now()而不是DispatchTime上添加Double

您必须问他们。我怀疑他们是出于方便的考虑而选择DispatchTime(允许使用诸如Int之类的文字值),并且因为它允许您指定小于一秒的时间间隔。 Double没有给您任何额外的功能(当然是为了消除此非常混乱的错误消息)。

结论

该错误来自于您通过尝试向2.5添加Int来混淆Swift的类型推断系统的事实。

其他建议的修复方法:

  1. 使用Int

  2. 使用DispatchTime Double明确记下DispatchTimeInterval代表什么。对于您的情况enum

答案 1 :(得分:2)

您需要使用 double 变量将其添加到case 0中。

.now()

答案 2 :(得分:1)

您可以使用文字进行DispatchTime数学

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

但不带Int变量,这就是模棱两可。有一个DispatchTimeInterval枚举可以传递一个Int变量

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