异步任务完成时的返回值

时间:2018-02-02 10:37:04

标签: ios swift

我想在appdelegate中实现performFetchWithCompletionHandler。我想做这样的事情

func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

DownloadManager.shared.startDownload(completion: { (done) in
if done{
completionHandler(.newData)
                }else{
                    completionHandler(.noData)
                }
})

我不确定如何在DownloadManager上实现此功能。它的实际实现看起来像

class DownloadManager{
    var pagesDownloadCompleted = false
    var imagesDownloadCompleted = false

// Function  to start the download     
    func startDownload(date: DataToDownload){
        ...
        downloadPages(pages)
        downloadImages(images)
    }
    }

// Function  to download the pages 
    func downloadPages(pages: Pages){
        ....
        if completed{
            pagesDownloadCompleted = true
        }
}

// Function  to download the images      
    func downloadImages(images: Images){
        ....
        if completed{
            imagesDownloadCompleted = true
        }
}

// Function  to check if the doanload is done       
    func downloadCompleted() -> Bool{
        return pagesDownloadCompleted == true && imagesDownloadCompleted ==  true
    }
    }
}

一种可能的解决方案是开始下载页面,当我完成后,我开始下载图像,当图像完成后,我返回true。但下载图像和页面将不会平行。你看到其他任何解决方案吗?

2 个答案:

答案 0 :(得分:0)

应该是这样的,你仍然需要处理失败和数据流,尝试使用dispatch group也是另一种解决方案:

class DownloadManager {
    var pagesDownloadCompleted = false
    var imagesDownloadCompleted = false

    // Function  to start the download
    func startDownload(date: String, completion: (_ completed: Bool)->()){

        downloadPages(pages: page) { (completed) in
            if completed {
                pagesDownloadCompleted = true
            }
            self.downloadCompleted(completion: completion)
        }
        downloadImages(images: image) { (completed) in
            if completed {
                imagesDownloadCompleted = true
            }
            self.downloadCompleted(completion: completion)
        }
    }

    // Function  to download the pages
    func downloadPages(pages: Pages, completion: (_ completed: Bool)->()){

        completion(true) //When download finished
    }

    // Function  to download the images
    func downloadImages(images: Images, completion: (_ completed: Bool)->()){

        completion(true) //When download finished
    }

    // Function  to check if the doanload is done
    func downloadCompleted(completion: (_ completed: Bool)->()){
        if pagesDownloadCompleted == true && imagesDownloadCompleted == true {
            completion(true)
        }
    }
}

答案 1 :(得分:0)

IMO使用DispatchGroup可以最好地解决这类问题。每当您开始下载时,请致电enter,此时呼叫已完成leavegroup.notify用于确定何时完成所有下载。

class DownloadManager{
    var group = DispatchGroup()

    func startDownload(date: DataToDownload) {
        downloadPages(pages)
        downloadImages(images)

        group.notify(queue: DispatchQueue.main) {
            // all downloads completed
        }
    }

    // Function  to download the pages
    func downloadPages(_ pages: Pages){
        group.enter()
        // do the download, when done, call:
        group.leave()
    }

    // Function  to download the images
    func downloadImages(_ images: Images){
        group.enter()
        // do the download, when done, call:
        group.leave()
    }
}