【问题标题】:Type of expression is ambiguous without more context error表达式类型不明确,没有更多上下文错误
【发布时间】:2019-02-01 16:44:15
【问题描述】:

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

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

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

【问题讨论】:

    标签: ios swift xcode dispatch-queue


    【解决方案1】:

    表达式类型不明确,没有更多上下文错误源于两个事实:

    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 解释为 DoubleDouble 类型符合 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() 是什么,因为无法添加DispatchTimeInt 来获得DispatchTime ,它决定 .now() 不是 DispatchTime 而是其他一些未知类型。因此,模棱两可的错误消息来自 Swift 无法确定 .now() 是什么。

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

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

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

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

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

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

    有一个相关的enum 类型DispatchTimeIntervalmicroseconds(Int)milliseconds(Int)nanoseconds(Int)seconds(Int)never。 Swift 知道如何添加 DispatchTimeDispatchTimeInterval,因此 Swift 能够将 .seconds(int) 解释为 DispatchTimeInterval,然后允许它将 .now() 解释为 DispatchTime

    为什么 Swift 设计者选择让您将 Double 添加到 DispatchTime 而不是 Int

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

    结论

    错误是因为您尝试将Int 添加到DispatchTime 从而混淆了Swift 的类型推断系统。

    其他答案建议的修复:

    1. 使用Double

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

    【讨论】:

    • 非常感谢!
    【解决方案2】:

    你可以用文字做DispatchTime数学

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

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

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

    【讨论】:

    • 嗨。我实际上是在等待更有经验的人回答:D。为什么可以将Double 变量添加到DispatchTime
    • 好问题,下一个问题?。我不知道DispatchTime 的原始值甚至是UInt64
    【解决方案3】:

    您需要使用 double 变量添加到.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
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-18
      • 2015-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多