我正在尝试将 escaping closure
代码转换为特定文件中的 async-await
代码。我坚持实施 async-await
部分,特别是是否仍然使用 do
块,以及 catch
和 resume
,或者不使用 do
块,并为代码行分配“try await URLSession.shared.dataTask(with: request)
”(在 File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.swift
中注释掉)在下面发布,并打算在解决方案中使用此文件)到一个变量,然后稍后使用该变量类似于文件 File2-GettingRestaurantBusinessDataUsingAsync-AwaitAndUsingCodable.swift
的方式,该文件将在本文下方进一步发布。
*注意: 我使用 async-await
和 codable
获取某个搜索城市(用户搜索)的餐厅业务数据,这是在不同的文件(和函数)中完成的。我遇到问题的文件是获取所选餐厅业务的详细信息(名称、地址、营业时间等),我没有在此文件中使用 codable
,因为我在执行此操作时获得的一些数据URL request
,我通过使用 NSDictionary
获得;不是codable
.
如何在我的文件中正确实现这个 async-await
概念?我正在执行此操作的文件是 File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.swift
,在这篇文章的下方进一步发布。
到目前为止,我已经发布了一些尝试的解决方案,但这些解决方案并不完整,因为我遇到了本文第一段中提到的问题。我知道它们不起作用,但这是我到目前为止的思考过程。这些解决方案尝试在我正在使用的代码文件下方,这些文件在下面进一步发布。
在尝试进行此当前实现之前,我使用以下文章来了解有关异步等待的更多信息:https://www.avanderlee.com/swift/async-await/.
我的代码:
我正在使用的代码文件:
我试图在以下文件中实现这个 escaping closure
到 async-await
概念的文件:
File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.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
//V1: Code for using escaping closure version code.
URLSession.shared.dataTask(with: request) { (data, response, error) in
//This version commented out right now, to show where I'm at with this proboem for clarity. This version is included in the solution attempts; both SoultionAttempt1 and SolutionAttempt2.
if let error = error {
completionHandler(nil, error)
}
//V2: Code for what I think is correct for using async-await version code. Not using the completionHandler here.
// URLSession.shared.dataTask(with: request)
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..*
//Commented out for now, because am going with version 2 below.
//V1: Uses escaping closure code version.
// completionHandler(selectedVenue, nil)
//V2: Used for Async/Await code version.
return selectedVenue
} catch {
print("Caught error")
}
}.resume()
}
}
文件(我指的是下面的文件;是 File2-GettingRestaurantBusinessDataUsingAsync-AwaitAndUsingCodable.swift
),在用户选择一个城市后使用异步等待获取初始餐厅业务数据,我正在使用该城市从 escaping closure
进行所述更改作为参考代码为上面async-await
中的File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.swift
代码:
File2-GettingRestaurantBusinessDataUsingAsync-AwaitAndUsingCodable.swift
:
import UIKit
import Foundation
import CoreLocation
class YelpApiSelectedRestaurantDetailViewInfo {
private var apiKey: String
init(apiKey: String) {
self.apiKey = apiKey
}
func searchBusinessDetailViewInfo(selectedRestaurantBusinessID: String) async throws -> SelectedRestaurantDetailViewInfo {
var resultsForTheSelectedRestaurantDetailViewInfo: SelectedRestaurantDetailViewInfo
// MARK: Make URL Request.
var urlComponents = URLComponents(string: "https://api.yelp.com/v3/businesses/\(selectedRestaurantBusinessID)")
guard let url = urlComponents?.url else {
throw URLError(.badURL)
}
var request = URLRequest(url: url)
request.setValue("Bearer \(self.apiKey)", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
let businessDetailViewInfoResults = try JSONDecoder().decode(SelectedRestaurantDetailViewInfo.self, from: data)
resultsForTheSelectedRestaurantDetailViewInfo = businessDetailViewInfoResults
return resultsForTheSelectedRestaurantDetailViewInfo
}
}
解决方案尝试:
*注:
-以下两个解决方案都尝试从代码行开始代码片段:URLSession.shared.dataTask(with: request) { (data, response, error) in
in File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.swift
,然后遍历该文件的其余部分,并在与该文件相同的终点结束(如文件 File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.swift
)。
-另外,这些解决方案尝试在文件中实现是 File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.swift
.
SolutionAttempt1-DoesntUseDoBlock.swift
:
///Initialize session and task
try await URLSession.shared.dataTask(with: request)
/// 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, business hours, etc..*
return selectedVenue
} catch {
print("Caught error")
}
}.resume()
}
}
*关于以下解决方案尝试文件的注意事项: 在我看来,这里的解决方案尝试 (SolutionAttempt2-DoesUseDoBlock.swift
) 可能不必包含 do
块的缩进,其中 do
块在“try await URLSession.shared”的范围内。 dataTask(with: request)” 行代码,但我包含了以下解决方案以尝试缩进,因为看起来 do
块需要在代码行 “try await URLSession.shared.dataTask(with: request)
” 的范围内,并且原始File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.swift
的文件版本,使用转义闭包(不是这里正在编辑/处理的文件)在代码范围的“do
”行内有 URLSession.shared.dataTask(with: request) { (data, response, error) in
块,它与代码中的“try await URLSession.shared.dataTask(with: request)
”行位于相同的位置这个 SolutionAttempt2-DoesUseDoBlock.swift
文件在下面。
SolutionAttempt2-DoesUseDoBlock.swift
:
///Initialize session and task
try await URLSession.shared.dataTask(with: request)
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 seelctedRestarauntDetailViewInfo 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, business hours, etc.*
return selectedVenue
} catch {
print("Caught error")
}
}.resume()
}
}
谢谢!