首页 > 解决方案 > 在 Swift 上发出多个网络请求

问题描述

我正在尝试从学校课程目录网站下载数据。我在变量 UrlBook 中有 64 个 Url。我已经成功编写了代码来下载课程集合,并使用完成处理程序方法将它们从单个 url转换为单个主题对象。我真的不知道我应该如何实现从 64 url​​ 收集所有主题并最终将它们变成目录对象(它包含主题对象列表)。

我已经阅读了很多关于异步和同步处理的文章和帖子,这让我很困惑。我非常感谢简单直接的代码来帮助我解决这个问题。感谢你们!

let urlBook = getUrlFromBook()

func fetchClassInfo(url:URL,completion: @escaping ([clase])-> Void){
    let task = URLSession.shared.dataTask(with: url){(data, response, error) in
        let jsonDecoder = JSONDecoder()
        if let data = data,
            let collection:[clase] = try?  jsonDecoder.decode([clase].self, from: data){
            completion(collection)
        }else{
            print("Either no data was returned, or data was not properly decoded.")
            //completion(nil)
        }
    }
    task.resume()
}

fetchClassInfo(url:urlBook.book[0]){(clase) in
    let newSubject = makeNewSubject(subjectIndex: 0, collectionOfCourse: clase)
    var masterCatalog = catalog(subjectCollection: [])
     masterCatalog.addSubject(newSubject: newSubject)

    }

标签: swiftcompletionhandlerurlsession

解决方案


您基本上可以创建如下所示的逻辑。这个函数接受一个 url 列表并返回一个完整的 Subject 列表。您可以根据需要修改模型等。在这个函数中;DispatchGroup是在调用之前等待所有请求完成,completion并且DispatchQueue在将主题附加到数组时防止“数据竞争”。

func downloadUrls(urls: [URL], completion: @escaping ([Subject]) -> Void) {
    var subjectCollection: [Subject] = []    
    let urlDownloadQueue = DispatchQueue(label: "com.urlDownloader.urlqueue")
    let urlDownloadGroup = DispatchGroup()

    urls.forEach { (url) in
        urlDownloadGroup.enter()

        URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
            guard let data = data, 
                let subject = try? JSONDecoder().decode(Subject.self, from: data) else {                    
                // handle error                    
                urlDownloadQueue.async {
                    urlDownloadGroup.leave()
                }
                return
            }

            urlDownloadQueue.async {
                subjectCollection.append(subject)
                urlDownloadGroup.leave()
            }
        })
    }

    urlDownloadGroup.notify(queue: DispatchQueue.global()) {
        completion(subjectCollection)
    }
}

推荐阅读