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.

你问的不是问题。没有理由去"等待"。你也不能。你只需要异步地做你该做的事。同时,接口必须保持活跃;用户必须能够继续工作。因此不需要为"等待"

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

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

关键是:你不需要"等待":你只需要让所有不同的活动对某个共同的中心值做出贡献,该值"知道"何时意味着我们已经"完成",然后可以采取行动。

正如@Matt所说,你不能,也不应该等到Alamofire处理完你的请求。这就像雇人帮你跑腿,然后你停下来,坐在门口等他们回来。你还不如自己去办这件事。

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

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

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

与其等待请求完成,不如重构getStartData方法以接受一个完成处理程序,并在工作完成后使用来响应:

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请求位于第一个调用的完成块中。(这比我现在想做的编辑还要多。)

最新更新