没有更多上下文的情况下,表达式类型是不明确的(Swift)。

168

我正在升级一个项目到最新的Swift版本,但在代码的这一部分中出现了“表达式类型不明确,需要更多上下文”的错误。我似乎无法解决它。我尝试了不同的方法,但是无法使它正常工作。

问题出在这一行的语法上。

let imageToDeleteParameters  = imagesToDelete.map { ["id": $0.id, "url": $0.url.absoluteString, "_destroy": true] }

完整代码:

extension TutorialCreationRequest: WebserviceParametrable {
    func toParameters() -> [String: AnyObject] {
        let imageParameters = images.map { ["url": $0] }
        let imageToDeleteParameters  = imagesToDelete.map { ["id": $0.id, "url": $0.url.absoluteString, "_destroy": true] }
        return [
            "title": title,
            "is_draft": isDraft,
            "difficulty": difficulty,
            "duration": duration,
            "cost": cost,
            "user_id": userId,
            "description": description,
            "to_sell": toSell,
            "images": [imageParameters, imageToDeleteParameters].flatMap { $0 }
        ]
    }
}

4
Swift编译器错误像这样的官方文档在哪里可以找到? - orion elenzil
19个回答

117

当你的函数参数名称错误时,就会发生这种情况。

示例:

functionWithArguments(argumentNameWrong: , argumentName2: )

并且您声明了您的函数为:

functionWithArguments(argumentName1: , argumentName2: ){}

当您更改变量名称时,通常会出现这种情况。确保在这样做时进行重构。


这种情况发生在我进行合并/变基操作后,一项更改未被注意到。请注意! - KidIcarus271
3
对我来说,问题出在返回类型上。 - Kimi Chiu
对我来说,问题出在传入了格式不正确的参数(期望是一个数组,但实际上传入了一个数组切片)。 - Scott Fister
1
我的问题是参数类型。 - Jonathan García
1
这与函数参数有关,简而言之! - Yash Bedi
对我来说,传递参数时声明为未指定类型的变量。例如,var x 被更改为 var x: Int。 - Doug Null

73

如果您所标记的方法或属性的任何一部分尝试访问具有不正确类型的属性或方法,则可能会发生这种情况。

以下是故障排除清单,请确保:

  • 调用站点和实现中的参数类型匹配。
  • 调用站点和实现中的参数名称匹配。
  • 调用站点和实现中的方法名称匹配。
  • 在用法和实现(例如enumerated())中返回的属性或方法的值匹配。
  • 您没有重复的方法,其中包含具有潜在模糊类型的协议或范型。
  • 在使用类型推断时编译器可以推断出正确的类型。

策略

  • 尝试将您的方法拆分为更多的简单方法/实现。

例如,假设您在自定义类型的数组上运行compactMap。在传递给compactMap方法的闭包中,您初始化并返回另一个自定义结构体。当您遇到此错误时,很难确定代码的哪个部分违规。

  • 为了调试目的,您可以使用for in循环而不是compactMap
  • 您可以在for循环中将参数直接分配给常量,而不是传递它们。

到这个环节,你可能会有所领悟,比如,你原本想要赋值的属性实际上已经存在于该属性中,而且拥有你想要传递的实际值。


11
Swift报告错误时,有时会在方法的完全不相关的部分报告错误,而且错误信息中甚至没有暗示可能存在于方法的任何部分。此外,也没有提示问题出现在方法的哪个位置,使我们不得不盲目地寻找解决方案。知道编译器能够这样做,至少有所帮助。 - Andres Riofrio
7
讽刺的是,“错误没有更多上下文是含糊不清的。”只是开个玩笑。我认为共同点是类型不匹配。如果存在类型不匹配,你的代码的两个部分将不同步。编译器怎么知道哪一个是正确的?话虽如此,它可以通过计算一致的类型使用情况,并突出显示具有最少常见类型计数的不匹配来进行逻辑处理。 - ScottyBlades
5
请问您需要翻译的是:或者突出显示两者并告诉我它们关于类型的信息?任何内容都比目前完全不透明的错误信息要好。 - Andres Riofrio
@AndresRiofrio,听起来不错,如果你提交了PR,请告诉我,我很乐意查看它。 - ScottyBlades
确保调用点和实现中的参数类型匹配。 - Rahul Gaur
显示剩余2条评论

42

虽然这不是回答 这个 问题的答案,但我来这里寻找错误时也发现了这个有用的信息:

在我的情况下,当我尝试对一个数组使用没有添加.enumerated() 部分的 for(index,object) 循环时,我遇到了这个Swift错误...


1
我也不回答这个问题,但在使用SWIFT 5、XCode 12时,当我将CGFloat传递给需要Objc float的函数时,我遇到了这个错误。将CGFloat强制转换为float后,错误消失了。这个错误描述并不是很清楚,通常是指重复或相同的模糊性。 - PDG
1
@PDG 同样的,对我来说,我传递的值实际上并不存在。此外,模棱两可被定义为“可以有多种解释。怀疑或不确定。” - ReinstateMonica3167040

24
编译器无法确定字典的数据类型,因为它不是同种类型的值。你有不同类型的值。唯一的解决办法是将其设置为[String: Any],但这会使所有操作变得笨重难用。
return [
    "title": title,
    "is_draft": isDraft,
    "difficulty": difficulty,
    "duration": duration,
    "cost": cost,
    "user_id": userId,
    "description": description,
    "to_sell": toSell,
    "images": [imageParameters, imageToDeleteParameters].flatMap { $0 }
] as [String: Any]

这是一个结构体的工作。它将大大简化与这个数据结构的处理。


对我来说,将其改为结构体是正确的选择。我试图从一个Promise传递一个元组到另一个Promise,并且遇到了这个错误;将其转换为结构体让编译器满意了。我有点喜欢使用元组的代码风格,但这不是什么大问题——能够成功编译更好。 - James Toomey
@JamesToomey 嗯,元组无法符合协议,因此如果通过承诺传递值需要一些协议符合性,则元组无法满足该要求。每当您看到固定键映射到值时,您几乎总是会想“我应该在这里使用结构/类”。 - Alexander
@JamesToomey 这取决于 Promise 是否对其泛型参数 T 施加任何约束。 - Alexander
@JamesToomey 嗯,你可以使用typaalias MyCustomTuple = (String, Int),但问题在于,元组从根本上不适合封装数据。问题在于,你的MyCustomTuple与其他(String, Int)类型是等价的。因此,你无法强制执行类型内的任何不变量。假设你有一个包含数组和缓存以提高性能的max元素的类型。这种类型需要确保对它的所有操作都保留这个不变量(即随着数组的更改适当地更新缓存的最大元素)... - Alexander
@Alexander,完全有道理。这让我更好地了解何时使用元组更为合适。有时从功能的解释中很难得出这一点,但并不一定是更好的选择(或不是)。 - James Toomey
显示剩余4条评论

11

当函数参数的类型不匹配时,我遇到了这个消息。在我的情况下,参数是一个字符串,而不是一个URL。


1
相同。函数需要一个Int64,所以当我硬编码只是“param:1”时它很高兴,但当我使用一个常量而没有声明Int64部分并且只是一个整数时,“param:myConstantOne”导致错误。当然不是在参数处,而是在函数调用处。正如其他人指出的那样,这不是非常有帮助的! - ConfusionTowers

6

明确声明映射函数的输入应该能解决问题:

let imageToDeleteParameters  = imagesToDelete.map {
    (whatever : WhateverClass) -> Dictionary<String, Any> in
    ["id": whatever.id, "url": whatever.url.absoluteString, "_destroy": true]
}

将代码片段中的"$0"的真正类替换为"WhateverClass",它就应该能够工作。

6

当我在调用函数时,在参数之间加上逗号前面的空格,就会出现这个错误。

例如,我使用了以下代码:

myfunction(parameter1: parameter1 , parameter2: parameter2)

而它应该是这样的:
myfunction(parameter1: parameter1, parameter2: parameter2)

删除空格以消除错误信息。

那听起来像是编译器的一个错误,希望已经被修复了。 - clearlight

3

我的问题是没有默认值的参数。

我进行了更改。

let contaPadrao = RedeConta(
  agencia: cPadrao?.agencia,
  conta: cPadrao?.conta,
  dac: cPadrao?.dac
)

为了

let contaPadrao = RedeConta(
  agencia: cPadrao?.agencia ?? "",
  conta: cPadrao?.conta ?? "",
  dac: cPadrao?.dac ?? ""
)

3

对我来说,这个案例是有关类型推断的。 我将函数参数从int更改为float,但没有更新调用代码,编译器并没有警告我传递给函数的数据类型错误。

更改前

func myFunc(param:Int, parma2:Int) {}

func myFunc(param:Float, parma2:Float) {}

调用带有错误的代码

var param1:Int16 = 1
var param2:Int16 = 2
myFunc(param:param1, parma2:param2)// error here: Type of expression is ambiguous without more context

解决方法:

var param1:Float = 1.0f
var param2:Float = 2.0f
myFunc(param:param1, parma2:param2)// ok!

3
在我的情况下,当我没有在构造函数中添加可选属性时,就会显示此错误消息。
struct Event: Identifiable, Codable {

    var id: String
    var summary: String
    var description: String?
    // also has other props...

    init(id: String, summary: String, description: String?){
        self.id = id
        self.summary = summary
        self.description = description
    }
}

// skip pass description
// It show message "Type of expression is ambiguous without more context"
Event(
    id: "1",
    summary: "summary",
)

// pass description explicity pass nil to description
Event(
    id: "1",
    summary: "summary",
    description: nil
)

但似乎从未发生过。

我在我的沙盒中测试了这段代码,它显示更具体的警告。

var str = "Hello, playground"
struct User {
    var id: String
    var name: String?
    init(id: String, name: String?) {
        self.id = id
        self.name = name
    }
}

User(id: "hoge") // Missing argument for parameter 'name' in call

你需要设置默认值才能这样做:init(id: String, name: String? = nil)。 - DaSilva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接