在这种情况下,有人可以为我解释dispatch_async()

fuz*_*uzz 2 thread-safety dispatch swift

我在一个单独的类中有以下方法:

class API: NSObject {

    var data = NSData()
    var delegate: APIProtocol?

    func getItems(callback: (Array<Image>) -> ()) {
        let urlPath: NSString = "http://localhost:3000/files"
        let url = NSURL(string: urlPath)

        let request = NSMutableURLRequest(URL: url)
        request.HTTPMethod = "GET"
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        let config = NSURLSessionConfiguration.defaultSessionConfiguration() as NSURLSessionConfiguration
        let session = NSURLSession(configuration: config) as NSURLSession

        var dataTask = NSURLSessionDataTask()
        dataTask = session.dataTaskWithRequest(request) { (data, response, error) in
            if (error == nil) {
                println("API at URL \(url)")

                let responseArray = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as NSArray
                var images = Image[]()
                for item: AnyObject in responseArray {
                    var location = Image(dict: item as NSDictionary)
                    images.append(location)
                }
                var img = images[0] as Image
                callback(images)

                //self.delegate?.didReceiveResponse(responseArray)
            }

        }
        dataTask.resume()
    }
}
Run Code Online (Sandbox Code Playgroud)

tableViewself.tableView.reloadData()内部打电话时无法让我重新加载callback()直到我添加了dispatch_async()它.

我的问题是:

1)如果没有它,它为什么不能正常工作?现在它tableView正确地刷新它是正确的吗?

2)有没有其他方法让它工作而不必在主队列上添加调度?

api.getItems() { (theArray) in
    dispatch_async(dispatch_get_main_queue(), {
        self.images = theArray
        self.tableView.reloadData()
        if (viaPullToRefresh) {
            self.refreshControl.endRefreshing()
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*rve 6

创建NSURLSession时,您可以指定委托/完成队列.如果您未指定队列

会话创建一个串行操作队列,用于执行所有委托方法调用和完成处理程序调用.

因此,这意味着您的回调将在专用串行队列上调用.现在,必须在主队列上更新所有UI,这就是为什么tableView.reloadData()不起作用的原因.

要删除对main_queue的调度调用,请像这样创建会话

let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue.mainQueue())
Run Code Online (Sandbox Code Playgroud)