【问题标题】:async-await "Type of expression is ambiguous without more context" error - in swiftUIasync-await“表达式类型不明确,没有更多上下文”错误 - 在 swiftUI 中
【发布时间】:2021-11-11 00:49:51
【问题描述】:

在这一行DispatchQueue.main.async 我得到这个错误:

没有更多上下文的表达类型是模棱两可的

import Foundation

class ProductListViewModel: ObservableObject {
    @Published var productList = [Product]()
    let webService = WebService()
    
    func downloadData(url: URL) async {
        
        do {
            let product = try await webService.getData(url: url)
            DispatchQueue.main.async {
                self.productList = product.map(ProductViewModel.init)
            }
        } catch {
            print("error")
        }
    }
}

struct ProductViewModel {
    
    let productModel: Product
    var id: Int {
        productModel.id
    }
    var title: String {
        productModel.title
    }
    var price: Double {
        productModel.price
    }
    var description: String {
        productModel.description
    }
    var category: Category {
        productModel.category
    }
    var imageUrl: String {
        productModel.imageUrl
    }
    var rating: Rating {
        productModel.rating
    }
}

struct WebService {
    
    func getData(url: URL) async throws -> [Product] {
        let (data, _) = try await URLSession.shared.data(from: url)
        let product = try? JSONDecoder().decode([Product].self, from: data)
        return product ?? []
    }
}

【问题讨论】:

  • 请包含代码,而不是代码图片,不能被屏幕阅读器复制/粘贴、搜索或阅读
  • 好吧,对不起。我编辑了
  • 向我们展示 WebService。向我们展示 ProductViewModel。告诉我们productList。您向我们展示的代码中应该没有未知数。请阅读如何提供minimal reproducible example
  • 感谢您的建议。我是新用户和程序员。我会学习steakoverflow
  • 你最后做得很好!干得好。

标签: swift swiftui


【解决方案1】:

该错误(此处公认是非描述性且无益的)是因为您尝试将 [ProductViewModel](这是您的 map 返回的内容)设置为 productList,其类型为 [Product]

ProductViewModel 在这里似乎没有目的——它只是产品的相同包装。您可以将 do 块内的代码更改为:

let products = try await webService.getData(url: url)
DispatchQueue.main.async {
    self.productList = products
}

为了进一步重构,你应该用 @MainActor 注释你的 ProductListViewModel 以确保它的属性设置在主队列上,然后你可以摆脱 DispatchQueue.main.async 调用——新的 async/await API 没有' t 与 DispatchQueue 混合得很好,反之亦然。

@MainActor class ProductListViewModel: ObservableObject {
    @Published var productList = [Product]()
    let webService = WebService()
    
    func downloadData(url: URL) async {
        do {
            let products = try await webService.getData(url: url)
            self.productList = products
        } catch {
            print("error")
        }
    }
}

【讨论】:

  • 是的,很遗憾有时编译器仍然只是对这种类型不匹配挥手致意。我建议 OP 将此作为错误报告提交给 Apple;他们确实想要改进他们的错误消息,并且他们已经做了很多工作来使它们变得更好,所以他们肯定想听听这样的案例。
  • 对不起,我不能两次投票,因为您给出了两条非常有穿透力的建议。 :) 我只是建议你删除“你可以”——你的意思是“你必须”。使用 async/await 意味着您不得使用 DispatchQueue;他们在一起玩得不好。
  • @matt 谢谢——我很感激你的客气话。关于DispatchQueue,我将添加一个编辑。然而,作为一个有趣的技术点,虽然我同意尝试混合 DispatchQueueasync/await 存在一些潜在的意外行为,但我认为在这种情况下,它在技术上仍然可以按预期工作,正确的?我知道相反(试图强制 DispatchQueue 使用 @MainActor)是行不通的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
  • 2022-11-18
  • 1970-01-01
  • 2015-09-21
  • 1970-01-01
相关资源
最近更新 更多