Wait for download task to finish in NSURLSession

孤街醉人 提交于 2019-12-23 07:26:27

问题


My scenario looks like this: I have a class which has a function in it and this function makes a POST request to a server with NSURLSession. In another function which is not in that class I call that function with the task in it, which runs asynchronously I think. I'm encountering following problem: When I download the JSON response from the server and write it to a variable and return it, the variable I've written to is still nil since it didn't wait for the thread/task to finish downloading and returns the initial value which is nil.

So my question is how can I wait for that task to finish and then continue the whole program.

This is my class with the request function:

class DownloadTask {
var json:NSDictionary!
var cookie:String!
var responseString : NSString = ""

func forData(completion: (NSString) -> ()) {

    var theJSONData:NSData!
    do {
        theJSONData = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions())
    } catch _ {
        print("error")
    }

    let request = NSMutableURLRequest(URL: url)
    request.HTTPMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    if cookie != nil {
        request.setValue(cookie, forHTTPHeaderField: "Cookie")
    }
    request.HTTPBody = theJSONData

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in

        if error != nil {
            print("error")
            return
        } else {
            completion(NSString(data: data!, encoding: NSUTF8StringEncoding)!)
        }
    }
    task.resume()
}

}

And this is my calling code:

let task = DownloadTask()
task.forData { jsonString in
    do {
        if let json: NSDictionary = try NSJSONSerialization.JSONObjectWithData(jsonString.dataUsingEncoding(NSUTF8StringEncoding)!, options:  NSJSONReadingOptions.MutableContainers) as? NSDictionary {
            if json["error"] != nil {
                authenticated = false
            } else {
                let result = json["result"] as! NSDictionary
                user.personId = result["personId"] as! NSNumber
                user.sessionId = result["sessionId"] as! NSString
                print("test0")
                authenticated = true
            }
        }
    }
    catch _ {
        print("error")
    }
}
print("test1")

The output is:

test1
test0

And I can't acess the variables user.sessionId after that task.


回答1:


As I said before in the comments of the main post the download NSURLSession.sharedSession().dataTaskWithRequest(request) run synchronously to the main thread which means it downloads the data synchronously to the displaying. So in short the print("test0") will be executed when the dispatched thread is finished (aka downloaded the data). To fix this I had to use semaphores (I also combined the first code and the second code from the original question):

private func downloadData(completion: (String) -> ()) {
   let semaphore = dispatch_semaphore_create(0);
   let request = NSMutableURLRequest(URL: url)

   var theJSONData = NSData()
   do {
       theJSONData = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions())
   } catch {
       completion(String())
   }

   request.HTTPMethod = "POST"
   request.setValue("application/json", forHTTPHeaderField: "Content-Type")
   request.HTTPBody = theJSONData

   let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
       data, response, error in
       data == nil ? completion(String()) : completion(String(data: data!, encoding: NSUTF8StringEncoding)!)
       dispatch_semaphore_signal(semaphore);
   }
   task.resume()
   dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}

This may not be the most efficient nor the most elegant solution but in my case I really had to wait for the downloading to be finished else it shouldn't do anything.



来源:https://stackoverflow.com/questions/32950874/wait-for-download-task-to-finish-in-nsurlsession

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!