【问题标题】:Swift dispatch_async from functionSwift dispatch_async 来自函数
【发布时间】:2015-09-20 23:14:40
【问题描述】:

如何等到函数从 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.. 的例子。

【问题讨论】:

  • 等什么?什么数据都进来了才能做什么?
  • 删除加载微调器,或类似的东西..在getStartData()中的所有请求都完成之后..
  • 不,不是“类似的东西”。请明确点。你有什么理由等到一切都结束?看,你在想这一切都是错的。你不“等待”。您不能让用户“等待”。你做事是异步的,只是在你去的时候不断更新。
  • 我知道,但是我想在两个请求都完成后删除微调器,有什么优雅的方法吗?

标签: ios swift alamofire dispatch-async


【解决方案1】:

你问的不是问题。 没有理由“等待”。你也不能。你只是做你所做的,异步的。同时界面必须保持活跃;用户必须能够继续工作。因此,没有什么可以“等待”

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

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

重点是:您不必“等待”:您只需让所有不同的活动促成一些共同的核心价值,即“知道”何时这意味着我们已经“完成”并可以采取行动。

【讨论】:

  • 你有什么例子吗?
  • 如果你真的感兴趣的话,NSProgress 上有一个完整的 WWDC 2015 视频。但是您实际上并不需要 NSProgress;您可以只增加或减少 KVO 可观察的实例变量(当然要小心线程)。关键是:您不必“等待”:您只需让所有不同的活动促成一些共同的核心价值,即“知道”何时这意味着我们已经“完成”并可以采取行动。 — 我想我会把它添加到我的答案中。
  • 我会试试你的建议。谢谢。
【解决方案2】:

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

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

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

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

您应该重构您的 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 请求位于第一个调用的完成块内。 (这比我现在有心情做的编辑要多。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 2017-01-18
    • 1970-01-01
    相关资源
    最近更新 更多