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

时间:2014-06-20 08:17:36

标签: thread-safety swift dispatch

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

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()
    }
}

tableView内拨打self.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()
        }
    })
}

1 个答案:

答案 0 :(得分:6)

创建NSURLSession时,您可以指定委托/完成队列。如果您没有指定队列

  

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

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

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

let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue.mainQueue())