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

9udxz4iz  于 2023-01-12  发布在  Swift
关注(0)|答案(4)|浏览(140)

我如何修复此代码,使它不会给予错误:表达式类型在没有更多上下文的情况下不明确?

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

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

ymzxtsji

ymzxtsji1#

    • 表达式类型不明确,没有更多上下文**错误源于两个事实:
  1. Swift不知道如何添加DispatchTimeInt
    1.由于事实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()是什么,因为没有办法把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类型DispatchTimeInterval,它有microseconds(Int)milliseconds(Int)nanoseconds(Int)seconds(Int)never,Swift知道如何添加DispatchTimeDispatchTimeInterval,因此Swift能够将.seconds(int)解释为DispatchTimeInterval,然后允许它将.now()解释为DispatchTime
为什么Swift的设计者选择让您将Double添加到DispatchTime,而不是Int
我怀疑他们选择Double是出于方便(允许使用像2.5这样的文字值),也是因为它允许您指定小于1秒的时间间隔。Int没有给您任何额外的功能(当然,除了消除这个非常混乱的错误消息)。

    • 结论**

错误来自这样一个事实,即您试图将Int添加到DispatchTime,从而混淆了Swift的类型推理系统。
其他答案建议的修复方法:
1.使用Double

    • 或**

1.使用DispatchTimeIntervalenum来明确地指出你的Int代表什么。

7ivaypg9

7ivaypg92#

您需要使用一个 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
}
cbwuti44

cbwuti443#

您可以使用文字执行DispatchTime数学运算

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

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

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

lymnna714#

我得到了同样的错误,对我来说,这段代码工作

let delay = Int64(120)
        
        DispatchQueue.main.async {
            Timer.scheduledTimer(withTimeInterval: TimeInterval(delay), repeats: false) { (timer) in
                // do stuff
            }
        }

相关问题