尝试从闭包访问返回的字符串时出现“无法将类型'()'的返回表达式转换为返回类型'String'”编译器错误

"Cannot convert return expression of type '()' to return type 'String'" compiler error when trying to access returned string from closure

提问人:Tardik 提问时间:9/1/2023 最后编辑:HangarRashTardik 更新时间:9/1/2023 访问量:63

问:

func requestList(completionParameter: @escaping (String) -> String ) {
    let url = URL(string: "https://www.google.de")!
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            let message = error.localizedDescription
            completionParameter(message)
        }
        if let response = response {
            let message = response.mimeType!
            completionParameter(message)
        }
    }
    task.resume()
}

func printer() -> String {
    let dspmsg = requestList(completionParameter: { message1 -> String in
        let t = type(of: message1)
        print(t)
        return message1
        })
    return dspmsg

返回的值显然是,但是当我检查闭包内部的内容时,我总是得到预期的文本,并且它的类型是 .在使用该函数之前,我尝试直接打印闭包的返回值,这导致我犯了同样的错误。dspmsgVoidmessage1completionParameterrequestListStringprinter()

我的目标是请求网站数据并在关闭之外使用它。

我怀疑返回发生在完成之前。 但正如我所说,直接打印返回并规避时序问题,打印一个空元组,据我所知,它等于 .printer()completionParameterVoid

Swift 闭包 URLCsession

评论

1赞 Leo Dabus 9/1/2023
不能将异步方法转换为同步方法。
0赞 matt 9/1/2023
programmingios.net/......
0赞 Tardik 9/1/2023
在阅读了您的回复后,我意识到当我谈论时机时,我走在正确的轨道上。我阅读了关于异步性的文章,我想我现在才开始意识到实际变化有多大;例如,即使是 print 语句也不会等待异步代码完成。我现在通过删除打印机函数并在我的文本字段中使用 onAppear 并将 requestList 函数及其 completionParameter 移动到其中来解决我的问题。
1赞 Tardik 9/1/2023
另外,在我看来,那个“programmingios”网站很好地解释了这个问题,谢谢你的链接!
0赞 La pieuvre 9/1/2023
更具体地说,代码中的问题是返回字符串的函数不是您调用的函数。 返回 Void(相当于 ()),然后传递到稍后将执行的闭包,并将返回一个字符串。因此,您的困惑。因此出现错误消息requestListrequestListCannot convert () to String

答:

0赞 Leo Dabus 9/1/2023 #1

你应该看看 Swift 中的 Async/Await 并发。您可以尝试以下操作:

  1. 创建异步方法并使用 URLSession 异步方法data(from: URL)

func requestList() async -> String {
    let url = URL(string: "https://www.google.de")!
    do {
        let (_, response) = try await URLSession.shared.data(from: url)
        guard let mime = response.mimeType else {
            throw URLError(.unknown)
        }
        return mime
    } catch {
       return error.localizedDescription
    }
}

  1. 将打印机方法也声明为异步:

func printer() async -> String {
    let dspmsg = await requestList()
    print(dspmsg)
    return dspmsg
}
  1. 然后,您可以使用 await 调用它

Task {
    let string = await printer() // text/html
}

评论

1赞 Tardik 9/1/2023
这个答案以及链接的文章帮助我解决了我的问题。