Swift 从 2 个 URLSession 返回数据

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

我想使用 Spotify 的 API 检索顶级艺术家和曲目数据。这是我获取顶级艺术家数据的代码:

func getTopArtistsData(accessToken: String, timeRange: String, completionHandler: @escaping (TopArtistsData?, Error?) -> Void){
        var request = URLRequest(url: URL(string: "https://api.spotify.com/v1/me/top/artists?time_range=\(timeRange)")!)
        request.httpMethod = "GET"
        request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

        URLSession.shared.dataTask(with: request) { (data, response, error) in
            let result = self.parseJSONTopArtists(topData: data!)
            completionHandler(result, nil)
        
        }.resume()
    }

但我想在同一个函数中使用 api.spotify.com/v1/me/top/tracks 执行第二个请求,因此completionHandler 将返回艺术家和曲目数据。如何做到这一点?

swift networking
1个回答
1
投票

您有多种选择。

  1. 现代技术 -> 异步/等待
  2. 很好的旧 GCD -> DispatchGroup 正如 @Larme 在对你的问题的评论中所建议的。 (并行运行)
  3. getTopArtistsData
    内部以肮脏的方式链接请求。 (串行运行)

为了避免过于复杂,GCD 在这里应该可以正常工作。

func getTopArtistsData(accessToken: String, timeRange: String, completionHandler: @escaping (TopArtistsData?, TopTracksData?) -> Void) {

    var artistsRequest = URLRequest(url: URL(string: "https://api.spotify.com/v1/me/top/artists?time_range=\(timeRange)")!)
    artistsRequest.httpMethod = "GET"
    artistsRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

    var tracksRequest = URLRequest(url: URL(string: "https://api.spotify.com/v1/me/top/tracks")!)
    tracksRequest.httpMethod = "GET"
    tracksRequest.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

    let group = DispatchGroup()

    var topArtists: TopArtistsData?
    var topTracks: TopTracksData?

    group.enter()
    URLSession.shared.dataTask(with: artistsRequest) { (data, response, error) in
        topArtists = self.parseJSONTopArtists(topData: data!)
        group.leave()
    }.resume()

    group.enter()
    URLSession.shared.dataTask(with: tracksRequest) { (data, response, error) in
        topTracks = self.parseJSONTopTracks(topData: data!)
        group.leave()
    }.resume()

    group.notify(queue: DispatchQueue.main) {
        completionHandler(topArtists, topTracks)
    }
}

请注意,这是您需要的非常粗略的示例,但它应该可以解决问题。

还有很多事情需要考虑,比如消除强制展开、在网络请求中不要强烈捕获 self、错误处理等等。

PS:主线程上不会调用包含(数据、响应、错误)的 URLSession 数据任务完成块,因此尝试更新 UI 将导致问题。在我的示例中,DispatchGroup 将在主线程上执行它的块,因此我们在这里是安全的。

© www.soinside.com 2019 - 2024. All rights reserved.