【问题标题】:Type of expression is ambiguous without more context Swift没有更多上下文 Swift 的表达式类型是模棱两可的
【发布时间】:2017-04-15 03:26:16
【问题描述】:

在我尝试升级到最新 Swift 版本的项目的这部分代码中,我得到一个“Type of expression is ambiguous without more context”。我似乎无法弄清楚。我尝试了不同的方法,但无法正常工作。

问题出在这一行的语法上

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 }
        ]
    }
}

【问题讨论】:

    标签: swift swift3


    【解决方案1】:

    当您有一个参数名称错误的函数时会发生这种情况。

    例子:

    functionWithArguments(argumentNameWrong: , argumentName2: )
    

    你将你的函数声明为:

    functionWithArguments(argumentName1: , argumentName2: ){}
    

    这通常发生在您更改变量的名称时。确保在执行此操作时进行重构。

    【讨论】:

    • 在合并/rebase 后发生在我身上,并且发生了变化。当心!
    • 对我来说,这是返回类型的问题。
    • 对我来说,结果是传入的参数格式错误(当期望数组时是数组切片)。
    • 我的问题是参数类型
    • 简而言之跟函数参数有关!
    【解决方案2】:

    如果突出显示的方法或属性的任何部分试图访问类型不正确的属性或方法,就会发生这种情况。

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

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

    策略

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

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

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

    此时,您可能会意识到,例如,您认为要分配的属性实际上有一个属性,该属性具有您要传递的实际值。

    【讨论】:

    • Swift 会在一个完全不相关的方法部分报告错误,甚至没有在错误消息中暗示它可能在方法。再者,问题出在方法上没有任何提示,迫使我们盲目地去寻找解决方案。至少知道编译器可以做到这一点会有所帮助。
    • 具有讽刺意味的是“错误在没有更多上下文的情况下是模棱两可的。”只是开玩笑。我认为共同的线程是类型不匹配。如果存在类型不匹配,则代码的两个部分会不同步。编译器应该如何知道您认为哪一个是正确的?也就是说,它可能有一些逻辑来计算一致的类型使用情况,然后用最少的常见类型突出显示不匹配的情况。
    • 或者突出显示两者并告诉我它对它们的类​​型了解多少?任何事情都比我们目前得到的完全不透明的错误信息要好。
    • @AndresRiofrio,对我来说听起来不错,如果你做 PR,请告诉我,我很乐意去看看。
    【解决方案3】:

    不是这个问题的答案,但是当我来到这里寻找错误时,其他人可能会发现这也很有用:

    对我来说,当我尝试在数组上使用 for (index, object) 循环而不添加 .enumerated() 部分时,我遇到了这个 Swift 错误...

    【讨论】:

    • 我也没有回答这个问题,但是当我将 CGFloat 传递给需要 Objc 浮点数的函数时,我在 SWIFT 5、XCode 12 上收到了这个错误。当我将 CGFloat 转换为浮动时,错误就消失了。不是最具描述性的错误,歧义通常是指重复或相同。
    • @PDG 同样,对我来说,我传入的值实际上并不存在。此外,歧义被定义为“对多种解释持开放态度。可疑或不确定。”
    【解决方案4】:

    编译器无法确定字典的类型,因为它不是同质的。您有不同类型的值。解决此问题的唯一方法是将其设为[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 并收到此错误;转换为结构使编译器感到高兴。我有点喜欢使用元组的代码外观,但没什么大不了的——编译它会更好。
    • @JamesToomey 元组不符合协议,所以如果通过承诺传递一个值需要一些协议一致性,元组就不能满足这个要求。每当您看到固定键到值的映射时,您几乎应该总是认为“我应该在这里使用结构/类”。
    • @Alexander,如果 Promise 允许您传回这样的泛型类型:func RunAndReturnPromise() -> Promise<T>,那么在这种情况下元组是否不被视为有效类型?
    • @JamesToomey 这取决于Promise 是否对其通用参数T 施加任何约束。
    • @Alexander,我做了更多的阅读/实验,我想我写错了返回参数。如果我先声明Promise< (String, Int) >,然后再声明resolve( ("a", 5) ),它就可以工作。我仍然认为从长远来看,Promise<MyCustomStruct> 的代码更清晰,所以我很高兴我遇到了你的答案。就像您在原始答案中提到的那样,当数据类型变得越来越复杂时(我可能会这样),将其抽象为结构或类要容易得多。
    【解决方案5】:

    当函数参数的类型不适合时,我收到此消息。在我的例子中,它是一个字符串而不是一个 URL。

    【讨论】:

    • 相同。函数需要一个 Int64,所以当我只硬编码“param: 1”时它很高兴,但是当我使用一个声明为没有 Int64 片段 & 只是一个整数的常量时,“param: myConstantOne”会导致错误。当然,不是在参数处,而是在函数调用处。正如其他人所指出的那样,这并不是完全有帮助的!
    【解决方案6】:

    当我在调用函数时在参数中的逗号前放置一个空格时出现此错误。

    例如,我用过:

    myfunction(parameter1: parameter1 , parameter2: parameter2)
    

    本来应该是这样的:

    myfunction(parameter1: parameter1, parameter2: parameter2)
    

    删除空间摆脱了错误提示

    【讨论】:

    • 这听起来像是一个编译器错误,希望已得到修复。
    【解决方案7】:

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

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

    在代码 sn-p 中用“$0”的真实类替换“WhateverClass”,它应该可以工作。

    【讨论】:

      【解决方案8】:

      对我来说,情况是类型推断 我已将函数参数从 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!
      

      【讨论】:

        【解决方案9】:

        在我的情况下,当我没有向构造函数添加可选属性时显示此错误消息。

        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)
        【解决方案10】:

        = 之前有两个 " "

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

        【讨论】:

          【解决方案11】:

          在我的例子中,它发生在 NSFetchedResultsController 上,原因是我为不同的模型定义了 NSFetchedResultsController,而不是创建了初始化请求(远程播放列表与播放列表):

            var fetchedPlaylistsController:NSFetchedResultsController<RemotePlaylist>!
          

          但通过请求另一个播放列表来启动它:

          let request = Playlist.createFetchRequest()
          fetchedPlaylistsController = NSFetchedResultsController(fetchRequest: request, ...
          

          【讨论】:

            【解决方案12】:

            在我的例子中,我在创建分发版本时遇到了这个错误,并且一个类引用了仅调试上下文方法。

            类似的东西。尝试为 Distribution build 编译下面的类。

            class MyClass {
               func sayHello() {
                  helloWorld()
                }
                
               #if DEBUG
                func helloWorld() {
                     print("Hello world")
                }
               #endif
            }
            

            【讨论】:

              【解决方案13】:

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

              我变了

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

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

              【讨论】:

                【解决方案14】:

                就我而言,我传递的参数具有可选的String 值。提供一个默认值(如果值为nil)为我解决了这个问题。

                我改变了这个 -

                router?.pushToDetailsScreen(
                gitHubRepositoryOwnerName: gitHubRepositoryDetails?[index].owner?.login,
                gitHubRepositoryName: gitHubRepositoryDetails?[index].name,
                avatarUrl: gitHubRepositoryDetails?[index].owner?.avatar_url)
                

                到这里-

                router?.pushToDetailsScreen(
                gitHubRepositoryOwnerName: gitHubRepositoryDetails?[index].owner?.login ?? "",
                gitHubRepositoryName: gitHubRepositoryDetails?[index].name ?? "",
                avatarUrl: gitHubRepositoryDetails?[index].owner?.avatar_url ?? "")
                

                【讨论】:

                  【解决方案15】:

                  确保是否有任何可用于扩展的委托方法,然后实施这些方法,错误就会消失。

                  【讨论】:

                    【解决方案16】:

                    作为 theEye 的回答,它不是对 this 问题的回答,但我也来到这里寻找错误,我发布了我的案例,因为其他人可能会发现这也很有用:

                    我在尝试计算两种不同类型的值时出错。

                    就我而言,我试图将CGFloat 除以Double

                    【讨论】:

                    • 这并不能真正回答问题。如果您有其他问题,可以点击 进行提问。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。
                    猜你喜欢
                    • 2016-12-10
                    • 2015-12-16
                    • 2018-02-15
                    • 2022-01-04
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多