如何将转义闭包代码转换为使用 URLSession 的异步等待代码?斯威夫特

问题描述 投票:0回答:0

我正在尝试将 escaping closure 代码转换为特定文件中的 async-await 代码。我坚持实施 async-await 部分,特别是是否仍然使用 do 块,以及 catchresume,或者不使用 do 块,并为代码行分配“try await URLSession.shared.dataTask(with: request)”(在 File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.swift 中注释掉)在下面发布,并打算在解决方案中使用此文件)到一个变量,然后稍后使用该变量类似于文件 File2-GettingRestaurantBusinessDataUsingAsync-AwaitAndUsingCodable.swift 的方式,该文件将在本文下方进一步发布。

*注意: 我使用 async-awaitcodable 获取某个搜索城市(用户搜索)的餐厅业务数据,这是在不同的文件(和函数)中完成的。我遇到问题的文件是获取所选餐厅业务的详细信息(名称、地址、营业时间等),我没有在此文件中使用 codable,因为我在执行此操作时获得的一些数据URL request,我通过使用 NSDictionary 获得;不是codable.

如何在我的文件中正确实现这个 async-await 概念?我正在执行此操作的文件是 File1-GettingSelectedRestaurantBusinessDataUsingAsync-AwaitAndNotUsingCodable.swift,在这篇文章的下方进一步发布。

到目前为止,我已经发布了一些尝试的解决方案,但这些解决方案并不完整,因为我遇到了本文第一段中提到的问题。我知道它们不起作用,但这是我到目前为止的思考过程。这些解决方案尝试在我正在使用的代码文件下方,这些文件在下面进一步发布。

在尝试进行此当前实现之前,我使用以下文章来了解有关异步等待的更多信息:https://www.avanderlee.com/swift/async-await/.

我的代码:

我正在使用的代码文件:

我试图在以下文件中实现这个 escaping closureasync-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()
    }
}

谢谢!

ios swift async-await closures urlsession
© www.soinside.com 2019 - 2024. All rights reserved.