Swift dispatch_async 来自函数

Swift dispatch_async from function

我如何才能等到函数从 alamofire 获取请求获取所有数据?

GetData.swift 文件:

import Foundation
import Alamofire
import SwiftyJSON
import ObjectMapper

func getStartData() -> Void {
    let sharedBranch = BranchSingleton.sharedInstance
    let sharedArticle = ArticleSingleton.sharedInstance

    Alamofire.request(.GET, Config().apiBranch)
        .responseJSON { request, response, result in
            let jsonObj = SwiftyJSON.JSON(result.value!)
            for obj in jsonObj {
                let branch = Mapper<Branch>().map(obj.1.rawString()!)
                sharedBranch.addBranch(branch!)
            }
    }
    Alamofire.request(.GET, Config().apiArticle)
        .responseJSON { request, response, result in
            let jsonObj = SwiftyJSON.JSON(result.value!)
            for obj in jsonObj {
                let article = Mapper<Article>().map(obj.1.rawString()!)
                sharedArticle.addArticle(article!)
            }
    }
}

ViewController.swift 文件:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        getStartData() // need to wait until all requests are finished then do print
        print(sharedArticle.articleList)

    }

}

SingletonObj.swift 文件:

import Foundation

class BranchSingleton {
    var branchList: [Branch] = []

    class var sharedInstance: BranchSingleton {
        struct Static {
            static let instance: BranchSingleton = BranchSingleton()
        }
        return Static.instance
    }

    func addBranch(branch: Branch) {
        branchList.append(branch)
    }
}
class ArticleSingleton {
    var articleList: [Article] = []

    class var sharedInstance: ArticleSingleton {
        struct Static {
            static let instance: ArticleSingleton = ArticleSingleton()
        }
        return Static.instance
    }

    func addArticle(article: Article) {
        articleList.append(article)
    }
}

我需要等到 getStartData() 完成,然后弹出单例数组..

我该怎么做?

这个 getStartData 包含超过 2 个请求,但我只是举了 2 个的例子..

你问的不是问题。 没有理由到"wait"。你也不能。你只是做你做的,异步的。同时界面必须保持活动状态;用户必须能够继续工作。因此 "wait" for.

没有任何意义

现在,如果问题是,当所有请求都完成后,如何以某种优雅的方式向应用程序的其余部分发送信号,一个好的答案是使用 NSProgress。所有不同的请求都可以促成一个共同的 NSProgress 对象。好处是它的 fractionCompleted 可以通过 KVO 观察到,所以当它大于或等于 1.0 时,你就完成了。

但你实际上并不需要 NSProgress;你可以只增加或减少一个 KVO 可观察的实例变量(当然要小心线程)。如果您知道有 n 个进程,那么您可以在 n 处启动一个变量,并让每个进程在完成时递减它; didSet 变量的观察者可以在我们达到零时采取行动。

关键是:你不需要 "wait":你只是让所有不同的活动都对一些共同的中心价值做出贡献,"knows" 这意味着我们已经 "finished" 并且然后可以采取行动。

正如@Matt 所说,您不能也不应该尝试等到 Alamofire 完成您的请求。这就像雇人 运行 跑腿,这样你就可以工作,然后停止一切,坐在门口,直到他们回来。您还不如自己 运行 去办事。

抛开类比,您还不如同步执行任务。然而,同步网络是一个非常糟糕的主意。它会冻结 UI 直到网络请求完成,如果出现问题,这可能会等待很长时间。

像 Alamofire 的请求方法这样的异步方法需要一个完成块,工作完成时应该是 运行 的代码块。

请求方法 returns 立即,甚至在请求发送到服务器之前,更不用说完成了。

与其等待请求完成,不如重构 getStartData 方法以获取完成处理程序,并在工作完成后使用 that 进行响应:

func getStartData(completion: () -> void) -> Void {
    let sharedBranch = BranchSingleton.sharedInstance
    let sharedArticle = ArticleSingleton.sharedInstance

    Alamofire.request(.GET, Config().apiBranch)
        .responseJSON { request, response, result in
            let jsonObj = SwiftyJSON.JSON(result.value!)
            for obj in jsonObj {
                let branch = Mapper<Branch>().map(obj.1.rawString()!)
                sharedBranch.addBranch(branch!)
            }
    }
    Alamofire.request(.GET, Config().apiArticle)
        .responseJSON { request, response, result in
            let jsonObj = SwiftyJSON.JSON(result.value!)
            for obj in jsonObj {
                let article = Mapper<Article>().map(obj.1.rawString()!)
                sharedArticle.addArticle(article!)
            }
    //At this point the Alamofire .GET request for Config().apiArticle 
    //is complete. Call our completion block (passed in as a parameter)
    completion()
    }
}


class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        getStartData() 
        {
          //This is a "trailing closure", a block of code passed to getStartData
          print("At this point, we've finished getting our data from Alamofire.")
          print(sharedArticle.articleList)
        }
    }
}

请注意,您的 getStartData 方法连续执行 2 个 Alamofire.request() 命令。如果第二个请求要求第一个请求完成,那么您将需要重组该代码,以便第二个 Alamofire 请求位于第一个调用的完成块内。 (这比我现在心情要做的编辑要多。)