Swift URL响应为零

时间:2015-03-05 02:20:50

标签: session swift return nsurl null

我创建了一个自定义DataManager类。在其中我想要获取方法中的数据并返回NSData对象以便之后转换为JSON。

我试图使用completionHandler获取数据,但没有运气:

class func fetchData() -> NSData? {
    var session = NSURLSession.sharedSession(),
        result = NSData?()
    let DataURL : NSURL = NSURL(string: "http://...file.json")!

    let sessionTask = session.dataTaskWithURL(DataURL, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
        result = data
    })
    sessionTask.resume()
    return result
}

提前致谢

1 个答案:

答案 0 :(得分:0)

dataTaskWithURL以异步方式运行。这意味着从completionHandler返回时不会调用fetchData闭包。因此,result尚未设置。

因此,您不应尝试从异步方法同步检索数据。相反,您应该自己使用异步完成处理程序模式:

class func fetchData(completionHandler: (NSData?, NSError?) -> ()) {
    let session = NSURLSession.sharedSession()
    let dataURL = NSURL(string: "http://...file.json")!

    let sessionTask = session.dataTaskWithURL(dataURL) { data, response, error in
        completionHandler(data, error)
    }
    sessionTask.resume()
}

你会这样称呼它:

MyClass.fetchData() { data, error in
    if data == nil {
        println("\(error)") 
    } else {
        // use `data` here
    }
}

// but do not try to use `data` here

顺便说一句,虽然上面解决了你的问题,但是当人们使用这种模式时,他们通常会想要用响应来更新UI,或者更新一些模型对象或者你有什么。但是completionHandler的{​​{1}}不会在主线程上运行。因此,很多人会将dataTaskWithURL的上述实现扩展为始终将fetchData发送回主队列:

completionHandler

现在,当你调用它时,你可以安全地更新模型对象和/或UI,知道这将在主线程上发生:

class func fetchData(completionHandler: (NSData?, NSError?) -> ()) {
    let session = NSURLSession.sharedSession()
    let dataURL = NSURL(string: "http://...file.json")!

    let sessionTask = session.dataTaskWithURL(dataURL) { data, response, error in
        dispatch_async(dispatch_get_main_queue()) {
            completionHandler(data, error)
        }
    }
    sessionTask.resume()
}

不可否认,您可能并不总是希望在主线程上运行此完成块,但通常除非执行极其计算密集的操作,否则上述操作非常常见。