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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52034323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 10:44:40  来源:igfitidea点击:

Type of expression is ambiguous without more context error

iosswiftxcodedispatch-queue

提问by D-A UK

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.

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

回答by vacawama

The Type of expression is ambiguous without more contexterror is stemming from two facts:

表达式的类型是模糊的没有更多的情况下错误是由两个事实而产生:

  1. Swift doesn't know how to add a DispatchTimeand an Int.
  2. Because of fact 1, Swift doesn't know how to interpret .now().
  1. Swift 不知道如何添加 aDispatchTimeInt
  2. 由于事实 1,Swift 不知道如何解释.now().


Swift doesn't know how to add a DispatchTimeand an Int

Swift 不知道如何添加一个DispatchTime和一个Int

This can be demonstrated with:

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

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

Binary operator '+' cannot be applied to operands of type 'DispatchTime' and 'Int'

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

but Swift does know how to add a DispatchTimeand a Double:

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

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

This compiles fine with no errors.

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

So why does DispatchQueue.main.asyncAfter(deadline: .now() + 5)work?

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

In this case, Swift is interpreting the integer literal 5as a Double. Type Doubleconforms to the protocol ExpressibleByIntegerLiteralwhich is what allows you to do:

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

let d: Double = 5

So in this case, it works because 5isn't an Int, it's a Double.

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

Because of fact 1, Swift doesn't know how to interpret .now()

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

When you tried to add an Intto .now():

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

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

the Swift type inference system got confused. Swift knows that it wants to pass a DispatchTimeto asyncAfter(deadline:), but it no longer could figure out what .now()is because there is no way to add a DispatchTimeand an Intto get a DispatchTime, it decided that .now()was not a DispatchTimebut some other unknown type. So the ambiguous error message is coming from Swift's inability to determine what .now()is.

Swift 类型推断系统变得混乱。Swift 知道它想将 a 传递DispatchTimeasyncAfter(deadline:),但它不再弄清楚是什么.now(),因为无法添加 aDispatchTime和 anInt来获得 a DispatchTime,它决定那.now()不是 aDispatchTime而是其他未知类型。所以模棱两可的错误信息来自 Swift 无法确定是什么.now()

If you make that explicit by saying DispatchTime.now(), then you get a more sensible error:

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

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

Binary operator '+' cannot be applied to operands of type 'DispatchTime' and 'Int'

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

As further evidence of this theory, if you provide Swift a way to add a DispatchTimeand an Int, Swift is happy with your original code:

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

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

So what is this .seconds()stuff? And how does it help solve the error?

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

There is a related enumtype DispatchTimeIntervalthat has cases microseconds(Int), milliseconds(Int), nanoseconds(Int), seconds(Int)and never. Swift knows how to add a DispatchTimeand a DispatchTimeInterval, so Swift is able to interpret .seconds(int)as a DispatchTimeIntervalwhich then allows it to interpret .now()as a DispatchTime.

还有一个相关的enum类型DispatchTimeInterval有案件microseconds(Int)milliseconds(Int)nanoseconds(Int)seconds(Int)never。Swift 知道如何添加 aDispatchTime和 a DispatchTimeInterval,因此 Swift 能够解释.seconds(int)为 aDispatchTimeInterval然后允许它解释.now()为 a DispatchTime

Why did the Swift designers choose to let you add a Doubleto a DispatchTimeand not an Int?

为什么 Swift 设计者选择让你在 aDouble中添加aDispatchTime而不是 an Int

You'd have to ask them. I suspect they chose the Doubleout of convenience (allowing literal values such as 2.5to be used) and because it allows you to specify time intervals smaller than one second. The Intdoesn't give you any extra capabilities (except of course for eliminating this very confusing error message).

你得问他们。我怀疑他们选择Double了方便(允许2.5使用诸如文字值)并且因为它允许您指定小于一秒的时间间隔。在Int不给你任何其他的功能(当然除了为消除这种非常混乱的错误消息)。

Conclusion

结论

The error is coming from the fact that you confused Swift's type inference system by trying to add an Intto a DispatchTime.

错误来自于您试图将 an 添加IntDispatchTime.

The fixes as the other answers suggested:

其他答案建议的修复:

  1. Use a Double.

    or

  2. Use the DispatchTimeIntervalenumto explicitly note what your Intrepresents. In your case .seconds(int).

  1. 使用一个Double.

    或者

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

回答by Rakesha Shastri

You need to use a doublevariable to add to the .now().

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

回答by vadian

You can do DispatchTimemath with literals

你可以DispatchTime用文字做数学

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

but not with an Intvariable, that's the ambiguity. There is a DispatchTimeIntervalenum to be able to pass an Intvariable

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

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