我正在尝试将某个文件中的escaping closure
代码转换为async-await
代码,更具体地说,我正在尝试不使用completionHandler
的方式来使用这个文件中的URLSession.shared.dataTask
代码行(具体地说,就是我正在使用的文件中的"URLSession.shared.dataTask(with: request) {
"代码行)。
在我正在进行更改的文件中,我收到错误:代码行为"Cannot find 'data' in scope
":"let json = try JSONSerialization.jsonObject(with: data!, options: [])
"。
我想我得到这个错误是因为我从来没有在文件中进一步定义"data
"。我没有在文件中得到这个问题,它使用escaping closure
作为文件函数中的整个代码,并使用completionHandler
作为"URLSession.shared.dataTask
"行代码(具体来说就是"URLSession.shared.dataTask(with: request) { (data, response, error) in
")。因此,在我正在使用的文件中,我在其中看到了这个错误消息,我尝试了一些解决方案,在"URLSession.shared.dataTask(with: request) {
"代码行之后创建了"data
"变量,并尝试了两种不同的变量赋值,但是没有一个成功。这些解决方案的尝试和我得到的错误是在下面的代码片段中。我在我工作的文件中做了这些解决方案的尝试,并且我有这个错误消息,它是File1-GetsDataNotUsingEscapingClosureAndNotUsingCompletionHandlerForURLSession.shared.dataTaskCode.swift
,它们包含在下面的文件中,并被注解掉。
我原本以为data
变量是在当前显示错误消息的代码行之前创建的(这一行代码在File1-GetsDataNotUsingEscapingClosureAndNotUsingCompletionHandlerForURLSession.shared.dataTaskCode.swift
中是"let json = try JSONSerialization.jsonObject(with: data!, options: [])
"),因此代码可能是正确的,可以正常工作,错误消息也会消失。
如何解决此错误?
我已经包含了我当前正在使用的文件,该文件具有上述错误,并且未使用escaping closure
执行操作的方式,也未在URLSession.shared.dataTask
代码行中使用completionHandler
(具体为"URLSession.shared.dataTask(with: request) {
"),命名为File1-GetsDataNotUsingEscapingClosureAndNotUsingCompletionHandlerForURLSession.shared.dataTaskCode.swift
。我还包括了标记为"Solution Attempt Version 1
"等的解决方案尝试,并且包括在运行该文件中具有该解决方案尝试的代码之后显示的错误。
我还包含了使用escaping closure
方法的原始文件,其中在URLSession.shared.dataTask
代码行中使用了completionHandler
(具体为"URLSession.shared.dataTask(with: request) { (data, response, error) in
"),命名为File2-GetsDataUsingEscapingClosureAndCompletionHandlerForURLSession.shared.dataTaskCode.swift
。
- 代码:**
File1-GetsDataNotUsingEscapingClosureAndNotUsingCompletionHandlerForURLSession.shared.dataTaskCode.swift
:
import Foundation
import UIKit
import CoreLocation
extension UIViewController {
func retrieveSelectedRestaurantDetailViewInfo(
selected_restaurant_business_ID: String) async throws -> SelectedRestaurantDetailViewInfoNotUsingCodable? {
// MARK: Make API Call
let apiKey = "API key"
/// Create URL
let baseURL =
"https://api.yelp.com/v3/businesses/\(selected_restaurant_business_ID)"
let url = URL(string: baseURL)
/// Creating Request
var request = URLRequest(url: url!)
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
///Initialize session and task
//Code for not using completionHandler:
URLSession.shared.dataTask(with: request) {
//Solution Attempt 1: Version of code for creating "data" variable, where the variable assignment is set to "Data".
//Got the error message for the above line of code "URLSession.shared.dataTask(with: request) {", saying "Contextual type for closure argument list expects 3 arguments, which cannot be implicitly ignored" with a "Fix" button below, and the text to the left of the "Fix" button being: "Insert '_,_,_ in '".
// var data = Data
//Solution Attempt 2: Version of code for creating "data" variable, where the variable assignment is set to "Data?".
//Got the same error message as Solution Attempt 1; Got the error message for the above line of code "URLSession.shared.dataTask(with: request) {", saying "Contextual type for closure argument list expects 3 arguments, which cannot be implicitly ignored" with a "Fix" button below, and the text to the left of the "Fix" button being: "Insert '_,_,_ in '".
// var data = Data?
do {
/// Read data as JSON
//The line of code below is where I'm getting the error message: "Cannot find 'data'" in.
let json = try JSONSerialization.jsonObject(with: data!, options: [])
/// Main dictionary
guard let responseDictionary = json as? NSDictionary else {return}
//Code for accessing restaraunt detail view info, and assigning it to selectedRestarauntDetailViewInfo view model thats a struct.
var selectedVenue = SelectedRestaurantDetailViewInfoNotUsingCodable()
//Rest of code for accessing restaraunt detail view info, and assigning it to seelctedRestarauntDetailViewInfo view model thats a struct.
selectedVenue.name = responseDictionary.value(forKey: "name") as? String
//*Rest of code for getting business info including address, hours, etc..*
return selectedVenue
} catch {
print("Caught error")
}
}.resume()
}
}
File2-GetsDataUsingEscapingClosureAndCompletionHandlerForURLSession.shared.dataTaskCode.swift
:
import Foundation
import UIKit
import CoreLocation
extension UIViewController {
func retrieveSelectedRestaurantDetailViewInfo(
selected_restaurant_business_ID: String,
completionHandler: @escaping (SelectedRestaurantDetailViewInfoNotUsingCodable?, Error?) -> Void) {
// MARK: Make API Call
let apiKey = "API key"
/// Create URL
let baseURL =
"https://api.yelp.com/v3/businesses/\(selected_restaurant_business_ID)"
let url = URL(string: baseURL)
/// Creating Request
var request = URLRequest(url: url!)
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
///Initialize session and task
//Code for using completionHandler:
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
completionHandler(nil, error)
}
do {
/// Read data as JSON
let json = try JSONSerialization.jsonObject(with: data!, options: [])
/// Main dictionary
guard let responseDictionary = json as? NSDictionary else {return}
//Code for accessing restaraunt detail view info, and assigning it to selectedRestarauntDetailViewInfo view model thats a struct.
var selectedVenue = SelectedRestaurantDetailViewInfoNotUsingCodable()
//Rest of code for accessing restaraunt detail view info, and assigning it to seelctedRestarauntDetailViewInfo view model thats a struct.
selectedVenue.name = responseDictionary.value(forKey: "name") as? String
//*Rest of code for getting business info including address, hours, etc..*
completionHandler(selectedVenue, nil)
} catch {
print("Caught error")
}
}.resume()
}
}
谢谢!
2条答案
按热度按时间kb5ga3dv1#
旧样式
dataTask
的转换如下:致:
不再涉及需要恢复的任务。数据和响应是直接返回值(作为元组)。
这是有效的,因为您是从声明为
async throws
的函数内部调用它的,所以如果对data
的调用抛出错误,它将传播到调用者。jw5wzhpr2#
在工作版本中,URLSession在调用闭包时将数据对象传递到闭包中:
这就是为什么你可以访问它。这在方法签名中很明显
在async/await中,数据直接从方法返回,但不引用返回的数据,需要修改代码以:
然后,您将能够使用所提供的
data
作为后续代码,就像您之前在闭包中所做的那样。